简体   繁体   English

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

[英]DRF: Post request with existing nested objects

I'm new to Django Rest Framework and nested serializers. 我是Django Rest Framework和嵌套序列化程序的新手。 I have a ModelSerializer named OrderSerialiser which contains two nested ModelSerializers : ProductSerializer and ClientSerializer. 我有一个名为OrderSerialiser的ModelSerializer,其中包含两个嵌套的ModelSerializer:ProductSerializer和ClientSerializer。

I want that new instances of the model client and the model product are created (Only if there is no already existing ones) when a post request is sent to the Order CreateAPI. 我希望在将发布请求发送到Order CreateAPI时创建模型客户端和模型产品的新实例(仅当尚不存在这些实例时)。 The solution I have found is to override the create method of the OrderSerializer. 我发现的解决方案是重写OrderSerializer的create方法。

It works fine when there is no instances of the client and the product having the same email and sku, but it returns an error saying that there is already existing objects ( client with the same email and a product with the same sku ) in the other case and does not get those existing objects,I noted that the create method in this case is not called , I think that I have to override the serializers.is_valid() method but I didn't figure out what I should do exactly . 当没有客户端和产品具有相同电子邮件和sku的实例时,它可以正常工作,但返回错误,表明另一个实例中已经存在对象(具有相同电子邮件的客户端和具有相同sku的产品)并没有得到这些现有对象,我注意到在这种情况下未调用create方法,我认为我必须重写serializers.is_valid()方法,但是我没有弄清楚应该怎么做。

models.py 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 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

Akamee, 赤目

one way I am used to solve this sort of problems is basically to, inside your serializers.py, do 我用来解决这类问题的一种方法基本上是在您的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')

This isn't ideal, but I did find a solution that solved my problem (I'm waiting to accept it as the answer, hoping someone else can do better) 这并不理想,但是我确实找到了解决问题的解决方案(我正等待接受它作为答案,希望其他人可以做得更好)

I have eliminated the validators for the field email in ClientSerializer and the field sku in Productserializer , and then checked the existence of objects manually. 我已经消除了ClientSerializer中的字段电子邮件和Productserializer中的字段sku的验证器,然后手动检查了对象的存在。

modification on serialzers.py 修改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