簡體   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