【问题标题】:DRF: How to validate a nested serializer's fields?DRF:如何验证嵌套序列化程序的字段?
【发布时间】:2019-02-19 23:16:21
【问题描述】:

我有models如下:

model: Business
    name

model: Employee
    business=FK(Business),
    user = FK(User)

model: Item
    title
    units

model: PurchaseInvoice
    business=FK(Business)
    employee = FK(Employee)
    invoice_no
    date

model: PurchasedItems
    parent_invoice=FK(PurchaseInvoice, related_name="purchased_items")
    item = FK(Item)
    quantity
    rate

和serializers.py:

class PurchasedItemPOSTSerializer(serializers.ModelSerializer):
    class Meta:
        model = PurchasedItem
        fields = ('item', 'quantity', 'rate')

    def validate_quantity(self, value):
        if value==0 or value is None:
            raise serializers.ValidationError("Invalid quantity")
        return value

    def validate_rate(self, value):
        if value==0 or value is None:
            raise serializers.ValidationError("rate?? Did you get it for free?")
        return value



class PurchaseInvoicePOSTSerializer(serializers.ModelSerializer):
    purchased_items = PurchasedItemPOSTSerializer(many=True)
    class Meta:
        model = PurchaseInvoice
        fields = ('invoice_no','date','purchased_items')

    def validate_purchased_items(self, value):
        if len(value)==0:
            raise serializers.ValidationError("atleast one item is required.")
        return value

    @transaction.atomic
    def create(self, validated_data):
        purchased_items_data = validated_data.pop('purchased_items')
        purchase_invoice = self.Meta.model.objects.create(**validated_data)
        for purchased_item in purchased_items_data:
            PurchasedItem.objects.create(purchase_invoice=purchase_invoice, **purchased_item)
        return invoice

和views.py

class PurchaseInvoiceViewSet(viewsets.ModelViewSet):
    serializer_class = PurchaseInvoicePOSTSerializer

    def get_serializer_context(self):
        return {'user': self.request.user, 'business_id': self.kwargs['business_id']}

    def get_queryset(self, **kwargs):
        return PurchaseInvoice.objects.filter(business__id=self.kwargs['business_id'])

    def perform_create(self, serializer):
        business = Business.objects.get(pk=self.kwargs['business_id'])
        employee = get_object_or_404(Employee, business=business, user=self.request.user)
        serializer.save(business=business, employee=employee)

通过POST发送的数据是:

{
    "invoice_no": "123",
    "date": "2018-07-13",
    "purchased_items": [
    {"item":1, "quantity":0, "rate":0}],
}

从上面的数据可以看出,validate_quantity 在quantity=0 和validate_rate 在rate=0 中对于item 中的item 中的purchased_items 都没有引发错误。

【问题讨论】:

  • 可以添加对应的视图类吗?
  • @JPG 已更新,请检查。
  • 能否同时添加 PurchasedItems 和 PurchaseInvoice 模型?
  • 已经在这里回答:stackoverflow.com/a/52357289/5710526

标签: django python-3.x django-models django-rest-framework


【解决方案1】:

您可以在序列化程序中添加自定义验证。例如:

from rest_framework import serializers
    class PurchasedItemPOSTSerializer(serializers.ModelSerializer):
        class Meta:
            model = PurchasedItem
            fields = ('item', 'quantity', 'rate')

        def validate(self, data):
            # custom anything validate
            quantity = data.get('quantity')
            # recheck validate in this
            if not quantity:
                raise serializers.ValidationError('not valid')
            return data

【讨论】:

  • 这不能回答问题。我已经在上面添加了验证。但这没有被调用。
  • 当然,您的 validate_rate 或 validate_quantity 不会被调用。但我的验证不是这样的。它是自定义验证,并且总是在方法 serializer.is_valid() 调用时调用。请尝试
  • 序列化程序中的验证顺序是:validate_<field> 然后validate。反正我已经解决了。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 2018-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多