繁体   English   中英

DRF:使用现有嵌套对象发布请求

[英]DRF: Post request with existing nested objects

我是Django Rest Framework和嵌套序列化程序的新手。 我有一个名为OrderSerialiser的ModelSerializer,其中包含两个嵌套的ModelSerializer:ProductSerializer和ClientSerializer。

我希望在将发布请求发送到Order CreateAPI时创建模型客户端和模型产品的新实例(仅当尚不存在这些实例时)。 我发现的解决方案是重写OrderSerializer的create方法。

当没有客户端和产品具有相同电子邮件和sku的实例时,它可以正常工作,但返回错误,表明另一个实例中已经存在对象(具有相同电子邮件的客户端和具有相同sku的产品)并没有得到这些现有对象,我注意到在这种情况下未调用create方法,我认为我必须重写serializers.is_valid()方法,但是我没有弄清楚应该怎么做。

models.py

class Client(models.Model):
    email = models.EmailField(
        verbose_name=_('Email address'),
        max_length=255,
        unique=True,
        primary_key=True
    )
    first_name = models.CharField(_('first name'), max_length=30)
    last_name = models.CharField(_('last name'), max_length=30)

class Product(models.Model):
    sku = models.CharField(
        verbose_name=_('SKU'),
        unique=True,
        max_length=120,
        primary_key=True
    )
    name = models.CharField(
        verbose_name=_('Name'),
        max_length=150
    )
    url = models.URLField(
        verbose_name=_('URL'),
        blank=True,
        null=True
    )


class Order(models.Model):
    client = models.ForeignKey(Client)
    products = models.ManyToManyField(
        Product,
        related_name= "orders",
        null=True,
        blank=True,
    )

serializers.py

class ProductSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('sku', 'name', 'url')

class ClientSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = ('email','first_name', 'last_name')



class OrderSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.email')
    client = ClientSerialiser()
    products = ProductSerialiser(many=True, required=False)

    class Meta:
        model = Order
        fields = ('id', 'client', products')

    def create(self, validated_data):
        client_data = validated_data.pop('client')
        try:
            client_instance = Client.objects.get(email=client_data['email'])
        except ObjectDoesNotExist:
            client_instance = Client.objects.create(**client_data)
        if 'products' in validated_data:
            products_data = validated_data.pop('products')
            order_instance = Order.objects.create(client=client_instance, **validated_data)
            for product_data in products_data:
                try :
                    product = Product.objects.get(sku=product_data['sku'])
                except ObjectDoesNotExist:
                    product = Product.objects.create(**product_data)
                product.orders.add(order_instance)
            return order_instance

        order_instance = Order.objects.create(client=client_instance, **validated_data)
        return order_instance

赤目

我用来解决这类问题的一种方法基本上是在您的serializers.py内部,

def validate(self, data):
    data = super(YourSerializer, self).validate(data)

    try:
       data['product'] = Product.objects.get(sku='bar')
    except Product.DoesNotExist:
       data['product'] = Product.object.create(sku='bar')

这并不理想,但是我确实找到了解决问题的解决方案(我正等待接受它作为答案,希望其他人可以做得更好)

我已经消除了ClientSerializer中的字段电子邮件和Productserializer中的字段sku的验证器,然后手动检查了对象的存在。

修改serialzers.py

class ProductSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('sku', 'name', 'url')
        extra_kwargs = {
            'sku': {
                'validators': []
            }
        }

class ClientSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = ('email', 'first_name', 'last_name')
        extra_kwargs = {
            'email': {
                'validators': []
            }
        }



class OrderSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.email')
    client = ClientSerialiser(partial=True)
    products = ProductSerialiser(many=True, required=False, partial=True)

    class Meta:
        model = Order
        fields = ('id','client', products')


    def create(self, validated_data):
        client_data = validated_data.pop('client')
        try:
            print "**************** client exists ***********************"
            client_instance = Client.objects.get(email=client_data['email'])
        except ObjectDoesNotExist:
            print "**************** creating a client    ***********************"
            client_instance = Client.objects.create(**client_data)
        if 'products' in validated_data:
            products_data = validated_data.pop('products')
            order_instance = Order.objects.create(client=client_instance, **validated_data)
            for product_data in products_data:
                try :
                    print "**************** Product exists ***********************"
                    product = Product.objects.get(sku=product_data['sku'])
                except ObjectDoesNotExist:
                    print "**************** creating object product ***********************"
                    product = Product.objects.create(**product_data)
                product.orders.add(order_instance)
            return order_instance

        order_instance = Order.objects.create(client=client_instance, **validated_data)
        return order_instance

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM