class ProductSerializer(serializers.ModelSerializer): producer_name = serializers.ReadOnlyField(source='producer.short_profile_name') department_for_customer = serializers.ReadOnlyField(source='department_for_customer.short_name') label = serializers.StringRelatedField(source='production_mode', read_only=True, many=True) customer_unit_price_amount = DecimalField(max_digits=8, decimal_places=2, source='customer_unit_price.amount', read_only=True) unit_deposit_amount = DecimalField(max_digits=8, decimal_places=2, source='unit_deposit.amount', read_only=True) class Meta: model = Product fields = ( 'reference', 'is_active', 'is_into_offer', 'producer_name', 'long_name', 'department_for_customer', 'order_unit', 'get_order_unit_display', 'order_average_weight', 'customer_unit_price_amount', 'unit_deposit_amount', 'vat_level', 'get_vat_level_display', 'customer_minimum_order_quantity', 'customer_increment_order_quantity', 'customer_alert_order_quantity', 'wrapped', 'stock', 'label', 'picture2', 'offer_description' )
class ShippingPointSerializer(serializers.GeoModelSerializer): lat = DecimalField(required=True, write_only=True) lng = DecimalField(required=True, write_only=True) def to_native(self, obj): result = super(ShippingPointSerializer, self).to_native(obj) if obj: # for working of REST framework GUI shipping_point = helpers.EloueNavette().get_shipping_point( obj.site_id, obj.position.x, obj.position.y, obj.type) if shipping_point: extra_info = PudoSerializer(data=shipping_point) if extra_info.is_valid(): result.update(extra_info.data) return result def restore_object(self, attrs, instance=None): lat = attrs.pop('lat') lng = attrs.pop('lng') obj = super(ShippingPointSerializer, self).restore_object(attrs, instance=instance) obj.position = Point((lat, lng)) return obj class Meta: model = models.ShippingPoint fields = ('id', 'site_id', 'pudo_id', 'position', 'type', 'lat', 'lng') read_only_fields = ('position', )
class DocumentEntrySerializer(AutoCleanSerializerMixin, serializers.HyperlinkedModelSerializer): product_code = serializers.SlugRelatedField(slug_field='value', read_only=True) total_before_tax = DecimalField(coerce_to_string=True, max_digits=None, decimal_places=2, read_only=True) total = DecimalField(coerce_to_string=True, max_digits=None, decimal_places=2, read_only=True) class Meta: model = DocumentEntry fields = ('id', 'description', 'unit', 'unit_price', 'quantity', 'total', 'total_before_tax', 'start_date', 'end_date', 'prorated', 'product_code') extra_kwargs = { 'unit_price': { 'coerce_to_string': True }, 'quantity': { 'coerce_to_string': True }, }
class BillableItemSerializer(Serializer): type = ChoiceField([ 'missed_reservation', 'tool_usage', 'area_access', 'consumable', 'staff_charge', 'training_session' ]) name = CharField(max_length=200, read_only=True) details = CharField(max_length=500, read_only=True) account = CharField(max_length=200, read_only=True) account_id = IntegerField(read_only=True) project = CharField(max_length=200, read_only=True) project_id = IntegerField(read_only=True) application = CharField(max_length=200, read_only=True) user = CharField(max_length=255, read_only=True) username = CharField(max_length=200, read_only=True) user_id = IntegerField(read_only=True) start = DateTimeField(read_only=True) end = DateTimeField(read_only=True) quantity = DecimalField(read_only=True, decimal_places=2, max_digits=8) def update(self, instance, validated_data): pass def create(self, validated_data): pass class Meta: fields = '__all__'
class TestDecimalRangeFieldWithChildAttribute(FieldValues): serializer_class = DecimalRangeSerializerWithChildAttribute field = DecimalRangeField(child=DecimalField(max_digits=5, decimal_places=2)) valid_inputs = [ ({'lower': '1', 'upper': 2., 'bounds': '[)'}, NumericRange(**{'lower': 1., 'upper': 2., 'bounds': '[)'})), ({'lower': 1., 'upper': 2.}, NumericRange(**{'lower': 1, 'upper': 2})), ({'lower': 1}, NumericRange(**{'lower': 1})), ({'upper': 1}, NumericRange(**{'upper': 1})), ({'empty': True}, NumericRange(**{'empty': True})), ({}, NumericRange()), ] invalid_inputs = [ ({'lower': 'a'}, ['A valid number is required.']), ({'upper': '123456'}, ['Ensure that there are no more than 5 digits in total.']), ({'lower': '9.123'}, ['Ensure that there are no more than 2 decimal places.']), ('not a dict', ['Expected a dictionary of items but got type "str".']), ] outputs = [ (NumericRange(**{'lower': '1.1', 'upper': '2'}), {'lower': '1.10', 'upper': '2.00', 'bounds': '[)'}), (NumericRange(**{'empty': True}), {'empty': True}), (NumericRange(), {'bounds': '[)', 'lower': None, 'upper': None}), ]
class LoadAccountSerializer(serializers.Serializer): """ First tried to just declare a djmoney.contrib.MoneyField, but currency was still missing from the representation. (The currency we can see in the documentation only comes to life when there is a database MoneyField in a model). """ amount = DecimalField(max_digits=12, decimal_places=2) amount_currency = ChoiceField(choices=CURRENCY_CHOICES, default=DEFAULT_CURRENCY)
class CartItemSerializer(serializers.ModelSerializer): item = ItemSerializer(read_only=True) total_price = DecimalField(max_digits=8, decimal_places=2, read_only=True) class Meta: model = CartItem fields = ['id', 'item', 'item_id', 'quantity', 'price', 'total_price'] read_only_fields = ['item', 'item_id', 'price', 'total_price']
class CartSerializer(serializers.ModelSerializer): items = CartItemSerializer(source='cart_items', many=True) total_cost = DecimalField(max_digits=8, decimal_places=2) class Meta: model = Cart fields = ['id', 'items', 'total_cost'] read_only_fields = ['items']
class CompanyChartSerializer(Serializer): """Serializer for the charts data.""" data = DecimalField(read_only=True, decimal_places=2, max_digits=3) date = DateTimeField(read_only=True) update = None create = None
class PudoSerializer(serializers.SimpleSerializer): name = CharField(blank=True) zipcode = CharField(blank=True) country = CharField(blank=True) city = CharField(blank=True) address = CharField(blank=True) distance = DecimalField(blank=True) is_open = BooleanField(blank=True) lat = DecimalField(blank=True) lng = DecimalField(blank=True) site_id = IntegerField(blank=True) pudo_id = CharField(blank=True) price = DecimalField(max_digits=10, decimal_places=2, required=False, blank=True) opening_dates = PudoOpeningDateSerializer(many=True, blank=True)
class ShippingPointListParamsSerializer(serializers.SimpleSerializer): lat = DecimalField(required=False, default=None) lng = DecimalField(required=False, default=None) address = CharField(required=False) search_type = IntegerField(required=True) def perform_validation(self, attrs): super(ShippingPointListParamsSerializer, self).perform_validation(attrs) position_in_params = 'lng' in attrs and 'lat' in attrs address_in_params = 'address' in attrs if not any([position_in_params, address_in_params]): msg = _(u'Latitude\longitude or address are required') self._errors['lng'] = msg self._errors['lat'] = msg self._errors['address'] = msg return attrs
class StatisticSerializer(Serializer): year = IntegerField() month = IntegerField() total = DecimalField(max_digits=10, decimal_places=2) def create(self, validated_data): super().create(self) def update(self, instance, validated_data): super().update(self, instance)
class FormattedCoursePriceSerializer(serializers.Serializer): """ Serializer for the format returned by `financialaid.api.get_formatted_course_price`. Primarily exists to convert `price` from decimal to string. """ program_id = IntegerField() price = DecimalField(max_digits=None, decimal_places=2) financial_aid_availability = BooleanField() has_financial_aid_request = BooleanField()
class ProducerSerializer(serializers.ModelSerializer): minimum_order_value_amount = DecimalField( max_digits=8, decimal_places=2, source='minimum_order_value.amount', read_only=True) class Meta: model = Producer fields = ('short_profile_name', 'long_profile_name', 'email', 'language', 'phone1', 'vat_id', 'address', 'invoice_by_basket', 'minimum_order_value_amount')
class SupplementLogCreateUpdateSerializer(BaseCreateUpdateSerializer): supplement_uuid = UUIDField(source="supplement.uuid") user = HiddenField(default=CurrentUserDefault()) uuid = UUIDField(required=False, read_only=True) notes = CharField( default="", trim_whitespace=True, required=False, allow_blank=True, ) quantity = DecimalField(decimal_places=4, max_digits=10, default=1) source = ChoiceField(INPUT_SOURCES_TUPLES, default=WEB_INPUT_SOURCE) class Meta: model = SupplementLog fields = ( "user", "uuid", "notes", "supplement_uuid", "source", "quantity", "time", "duration_minutes", ) def validate_supplement_uuid(self, value): user = self.context["request"].user validate_model_uuid(Supplement, uuid=value, user=user) return value def validate(self, validated_data): user = self.context["request"].user is_creating_instance = not self.instance if validated_data.get("supplement"): supplement_uuid = validated_data["supplement"]["uuid"] supplement = Supplement.objects.get(uuid=supplement_uuid, user=user) validated_data["supplement"] = supplement if is_creating_instance: if self.Meta.model.objects.filter( user=user, supplement=supplement, time=validated_data["time"], ).exists(): raise ValidationError( f"Fields user, supplement, and time are not unique!") return validated_data
class MovieModelSerializer(ModelSerializer): actors = ActorModelSerializer(many=True, read_only=True) genres = GenreModelSerializer(many=True, read_only=True) score = DecimalField(max_digits=4, decimal_places=2) def to_representation(self, instance): d = super().to_representation(instance) # type: dict return d class Meta: model = Movie fields = '__all__'
class AssetLocationBasketSerializer(DynamicFieldsModelSerializer): offer_discounts = OfferDiscountSerializer(many=True, required=False) total_excl_tax = DecimalField( decimal_places=2, max_digits=12, required=False) total_excl_tax_excl_discounts = DecimalField( decimal_places=2, max_digits=12, required=False) total_incl_tax = TaxIncludedDecimalField( excl_tax_field='total_excl_tax', decimal_places=2, max_digits=12, required=False) total_incl_tax_excl_discounts = TaxIncludedDecimalField( excl_tax_field='total_excl_tax_excl_discounts', decimal_places=2, max_digits=12, required=False) total_tax = TaxIncludedDecimalField( excl_tax_value=Decimal('0.00'), decimal_places=2, max_digits=12, required=False) currency = CharField(required=False) voucher_discounts = VoucherDiscountSerializer(many=True, required=False) lines = AssetLocationBasketLineSerializer(many=True, required=False) class Meta: model = Basket fields = '__all__'
class TotalIncludingZeroSerializer(serializers.BaseSerializer): """ Totals are serialized as a list of money instances. """ amount_serializer = DecimalField(max_digits=12, decimal_places=2) def to_representation(self, obj): # We cannot use djmoney.contrib.django_rest_framework.MoneyField because a total is not a field. # So we replicate the output. return [{ 'amount': TotalSerializer.amount_serializer.to_representation(money.amount), 'amount_currency': money.currency.code } for money in obj.monies()]
class CurrencyRateSerializer(Serializer): currency1 = CharField(max_length=3) currency2 = CharField(max_length=3) amount = DecimalField(max_digits=100, decimal_places=4) value2 = SerializerMethodField() def get_value2(self, obj): """ Calculates first currency in EUR and compares with other currency """ from_currency = CurrencyRate.objects.filter( currency=obj['currency1']).latest('date') to_currency = CurrencyRate.objects.filter( currency=obj['currency2']).latest('date') amount = Decimal(obj['amount']) return str(amount * to_currency.exchange_rate / from_currency.exchange_rate)
class RpmReadingSerializer(ModelSerializer): circumference = DecimalField(source="loom.circumference", read_only=True, decimal_places=3, max_digits=12) #tape_type foreignkey data quality = CharField(source="loom.tape_type.quality.name", read_only=True) denier = CharField(source="loom.tape_type.denier", read_only=True) color = CharField(source="loom.tape_type.color", read_only=True) #Bag_type foriegn key data width = FloatField(source="loom.bag_type.width", read_only=True) length = FloatField(source="loom.bag_type.length", read_only=True) frame = CharField(source="loom.bag_type.frame", read_only=True) color = CharField(source="loom.bag_type.color", read_only=True) weight = FloatField(source="loom.bag_type.weight", read_only=True) quantity = FloatField(source="loom.quantity", read_only=True) date_time = DateTimeField(source="loom.date_time", read_only=True) total = FloatField(read_only=True) class Meta: model = RpmReading fields = ( "total", "id", "machine_no", "rpm", "time", "meters", "state", "loom", "circumference", "quality", "denier", "color", "width", "length", "frame", "color", "weight", "quantity", "date_time", )
class ProductSerializer(ModelSerializer): is_on_sale = BooleanField(read_only=True) current_price = FloatField(read_only=True) description = CharField(min_length=2, max_length=200) cart_items = OrderSerializer(many=True, read_only=True) # price = FloatField(min_value=1.00, max_value=100000) price = DecimalField( min_value=1.00, max_value=100000, max_digits=None, decimal_places=2, ) sale_start = DateTimeField( required=False, input_formats=['%I:%M %p %d %B %Y'], format=None, allow_null=True, help_text='Accepted format is "12:01 PM 16 April 2019"', style={'input_type': 'text', 'placeholder': '12:01 AM 28 July 2019'}, ) sale_end = DateTimeField( required=False, input_formats=['%I:%M %p %d %B %Y'], format=None, allow_null=True, help_text='Accepted format is "12:01 PM 16 April 2019"', style={'input_type': 'text', 'placeholder': '12:01 AM 28 July 2019'}, ) photo = ImageField(default=None) warranty = FileField(write_only=True, default=None) class Meta: model = Product fields = ( 'id', 'name', 'description', 'price', 'sale_start', 'sale_end', 'is_on_sale', 'current_price', 'cart_items', 'photo', 'warranty', ) def update(self, instance, validated_data): if validated_data.get('warranty', None): instance.description += '\n\nWarranty Information:\n' instance.description += b'; '.join( validated_data['warranty'].readlines() ).decode('utf-8') return super().update(instance, validated_data) def create(self, validated_data): validated_data.pop('warranty') # remove return Product.objects.create(**validated_data)
class Meta: _permission_classes = ('rest_framework.permissions.AllowAny', ) _override_permission_classes = True default_related_name = 'author' _non_bulk_methods = ('post', ) _list_fields = ['name', 'hidden'] _detail_fields = [ 'name', 'registerDate', 'posts', 'phone', 'masked', 'decimal' ] _extra_serializer_classes = { 'serializer_class_update': UpdateAuthorSerializer, 'serializer_class_partial_update': UpdateAuthorSerializer, } _properties_groups = {"Main": ["id", "name"]} _override_detail_fields = { 'posts': RelatedListField(fields=['title'], related_name='post', view_type='table', serializer_class=RelatedPostSerializer), 'phone': PhoneField(allow_null=True, required=False), 'masked': MaskedField(allow_null=True, required=False, mask={'mask': '000-000'}), 'decimal': DecimalField(default='13.37', decimal_places=2, max_digits=5) } _nested = { 'post': { 'allow_append': False, 'model': 'test_proj.models.fields_testing.ExtraPost', 'arg': 'id' } }
class SupplementLogCreateUpdateSerializer(BaseCreateUpdateSerializer): supplement_uuid = UUIDField(source="supplement.uuid") # user = HiddenField(default=CurrentUserDefault()) # uuid = UUIDField(required=False, read_only=True) # notes = CharField( # default="", # trim_whitespace=True, # required=False, # allow_blank=True, # ) quantity = DecimalField(decimal_places=4, max_digits=10, default=1) source = ChoiceField(INPUT_SOURCES_TUPLES, default=WEB_INPUT_SOURCE) class Meta: model = SupplementLog fields = ( "user", "uuid", "notes", "supplement_uuid", "source", "quantity", "time", "duration_minutes", ) def validate_supplement_uuid(self, value): user = self.context["request"].user try: validate_model_uuid(uuid=value, model=Supplement, user=user) except ValidationError: # if it's an edit, don't allow someone to edit a log to a stack if self.instance: raise # we allow for supplement_stack_uuid to also be passed in here, a bit of a hack validate_model_uuid(uuid=value, model=SupplementStack, user=user) return value def validate(self, validated_data): """ This code isn't pretty, but it's because i'm jamming supplement stack and supplements in one view """ user = self.context["request"].user is_creating_instance = not self.instance if validated_data.get("supplement"): supplement = validated_data.pop("supplement") supplement_uuid = supplement["uuid"] try: supplement = Supplement.objects.get(uuid=supplement_uuid, user=user) validated_data["supplement"] = supplement except ObjectDoesNotExist: # don't allow supplement stacks if it's not a create operation if not is_creating_instance: raise # if it doesn't exist, it's a supplement stack stack = SupplementStack.objects.get(uuid=supplement_uuid, user=user) validated_data["stack"] = stack if is_creating_instance and validated_data.get("supplement"): if self.Meta.model.objects.filter( user=user, supplement=supplement, time=validated_data["time"], ).exists(): raise ValidationError( "Fields user, supplement, and time are not unique!") elif is_creating_instance and validated_data.get("stack"): stack = validated_data["stack"] stack_supplements = [ item.supplement for item in stack.compositions.all() ] for supplement in stack_supplements: if self.Meta.model.objects.filter( user=user, supplement=supplement, time=validated_data["time"], ).exists(): raise ValidationError( "Fields user, supplement, and time are not unique!") return validated_data def create(self, validated_data): if validated_data.get("supplement"): # normal drf serializers, change nothing return super().create(validated_data) elif validated_data.get("stack"): stack = validated_data.pop("stack") stack_compositions = stack.compositions.all() created_instances = [] for composition in stack_compositions: results = validated_data.copy() supplement = composition.supplement # a stack might have a quantity of 2 of something updated_quantity = results["quantity"] * composition.quantity results["supplement"] = supplement results["quantity"] = updated_quantity created_instance = self.Meta.model.objects.create(**results) created_instances.append(created_instance) return created_instances
class BalanceAddSerializer(Serializer): balance = DecimalField(max_digits=15, decimal_places=2)
'format': 'date' }, ), ( # DateTimeField DateTimeField(), { 'type': 'string', 'format': 'date-time' }, ), ( # DecimalField DecimalField( max_digits=4, decimal_places=2, validators=[MinValueValidator(10), MaxValueValidator(20)], ), { 'type': 'string', 'format': 'decimal', 'multipleOf': 0.01, 'maximum': 20, 'minimum': 10, }, ), ( # DecimalField DecimalField(max_digits=5, decimal_places=2, validators=[MinValueValidator(0)]),
class SupplementStackCompositionCreateUpdateSerializer( BaseCreateUpdateSerializer): supplement_uuid = UUIDField(source="supplement.uuid") stack_uuid = UUIDField(source="stack.uuid") quantity = DecimalField(decimal_places=4, max_digits=10, default=1) class Meta: model = SupplementStackComposition fields = ( "user", "uuid", "notes", "supplement_uuid", "stack_uuid", "quantity", ) def validate_supplement_uuid(self, value): user = self.context["request"].user validate_model_uuid(uuid=value, model=Supplement, user=user) return value def validate_stack_uuid(self, value): user = self.context["request"].user validate_model_uuid(uuid=value, model=SupplementStack, user=user) return value def validate(self, validated_data): user = self.context["request"].user is_creating_instance = not self.instance if validated_data.get("supplement"): supplement_uuid = validated_data.pop("supplement")["uuid"] supplement = Supplement.objects.get(uuid=supplement_uuid, user=user) validated_data["supplement"] = supplement if validated_data.get("stack"): stack_uuid = validated_data.pop("stack")["uuid"] stack = SupplementStack.objects.get(uuid=stack_uuid, user=user) validated_data["stack"] = stack # check for uniqueconstraints issues with creation # for updates, probably be a little bit easier # and skip for now if is_creating_instance: if self.Meta.model.objects.filter( user=user, stack=validated_data["stack"], supplement=validated_data["supplement"], ).exists(): raise ValidationError( "Fields supplement stack and supplement are not unique") else: # if this is changing a supplement in a stack, make sure no conflicts with other compositions if validated_data.get("supplement"): # if updating, make sure that there are no other compositions with the same stack materials if (self.Meta.model.objects.filter( user=user, stack=self.instance.stack, supplement=validated_data["supplement"], ).exclude(uuid=self.instance.uuid).exists()): raise ValidationError( "Fields supplement stack and supplement name are not unique. Only a unique supplement allowed per stack." ) return validated_data
class DecimalRangeField(RangeField): child = DecimalField(max_digits=None, decimal_places=None) range_type = NumericRange
class OrderSerializer(serializers.ModelSerializer): products = OrderPositionsSerializer( many=True, source="positions", ) user = UserSerializer(read_only=True, ) total_amount = DecimalField(max_digits=10, decimal_places=2, read_only=True) class Meta: model = Order fields = ('id', 'user', 'products', 'status', 'total_amount', 'created_at', 'updated_at') def create(self, validated_data): validated_data['user'] = self.context[ 'request'].user # Проставляем значения поля user по-умолчанию positions_data = validated_data.pop('positions') total_amount = 0 # Считаем и добавляем в validated_data total_amount if positions_data: for position in positions_data: total_amount += position['product_id'].price * position[ 'quantity'] validated_data['total_amount'] = total_amount order = super().create(validated_data) if positions_data: # Создаем поля в промежуточной таблице to_save = [] for position in positions_data: to_save.append( OrderPositions( product=position['product_id'], quantity=position['quantity'], order_id=order.id, )) OrderPositions.objects.bulk_create(to_save) return order def update(self, instance, validated_data): validated_data[ 'user'] = instance.user # Проставляем значения поля user из оригинального заказа positions_data = validated_data.pop('positions') total_amount = 0 # Считаем и добавляем в validated_data total_amount if positions_data: for position in positions_data: total_amount += position['product_id'].price * position[ 'quantity'] validated_data['total_amount'] = total_amount order = super().create(validated_data) if positions_data: # Создаем поля в промежуточной таблице to_save = [] for position in positions_data: to_save.append( OrderPositions( product=position['product_id'], quantity=position['quantity'], order_id=order.id, )) OrderPositions.objects.bulk_create(to_save) return order def validate(self, data): """Проверяем, что статус могут менять только админы""" if not self.context['request'].user.is_staff and 'status' in data: raise serializers.ValidationError('Status is read-only for users') if 'positions' in data: product_ids = set() for position in data['positions']: product_ids.add(position['product_id']) if len(product_ids) != len(data['positions']): raise serializers.ValidationError('Products should be unique') return data
def parse_decimal(value, max_digits=19, decimal_places=2): """Parses a decimal from a string.""" return _parse_value(value, DecimalField(max_digits, decimal_places))
class DecimalRangeSerializerWithChildAttribute(serializers.Serializer): range = DecimalRangeField(child=DecimalField(max_digits=5, decimal_places=2))