Django Rest框架|可写的多个嵌套关系

时间:2019-03-15 18:00:46

标签: python django django-rest-framework

我有一些模型,它们彼此嵌套。我想为2个序列化器进行批量创建,两者都与其他模型有关系。我查看了DRF上的文档,但是无法在我的代码中实现。

我这样发送json数据:

{
  'status':true,
  'products':[
              {
               'painting':{'amount':10}, 
               'product':{'id':12, }
              },
              {
               'painting':{'amount':10}, 
               'product':{'id':12, }
              }
             ],
   'customer':{ 'name':'Adnan',
                'address':{'country':'Turkey'}
              },
    'total':111

}

#models.py

class Address():
    ...
class Customer():
    address = models.ForeignKey(Address, ...)
class Painting():
    ...
class Product():
    ...
class Selling():
    customer = models.ForeignKey(Customer, ...)
    products = models.ManyToManyField(Product, through='SellingProduct')
class SellingProduct():
    selling = models.ForeignKey(Selling, ...)
    product = models.ForeignKey(Product, ...)
    painting = models.ForeignKey(Painting, ...)

这是我的serializers.py

class AddressSerializer():
    ...
class CustomerSerializer():
    address = AddressSerializer()
    ...
class PaintingSerializer():
    ...
class ProductSerializer():
    ...
class SellingProductSerializer():
    painting = PaintingSerializer()
    product = ProductSerializer()

class SellingSerializer():
    customer = CustomerSerializer()
    products = SellingProductSerializer(many=True)
    ...
    def create(self, validated_data):
        ...

如果我这样写:

class SellingSerializer():
    ...
    def create(self, validated_data):
        customer_data = validated_data.pop('customer')
        products_data = validated_data.pop('products')
        selling = Selling.objects.create(**validated_data) #i didn't pass customer here
        for product_data in products_data:
            SellingProducts.objects.create(selling=selling, **product_data)
        return selling

我收到此错误:

django.db.utils.IntegrityError: (1048, "Column 'customer_id' cannot be null")

如果我这样写:

class SellingSerializer():
    ...
    def create(self, validated_data):        
        selling = Selling.objects.create(**validated_data) #i didn't pass customer here        
        return selling

我收到此错误:

ValueError: Cannot assign "OrderedDict...
..Selling.customer must be a "Customer" instance
  • 如果类型为OrderedDict,我不知道如何提取或访问数据。我也该怎么做?

我想为“ Selling and SellingProduct,Paint”创建一个记录,并且我不想在每个请求中创建“ Customer”,“ Address”,“ Product”记录,而我将使用存在的数据(在前端选定)。

在此先感谢大家的帮助!

3 个答案:

答案 0 :(得分:2)

如果您进行了一些修改,您的第一种方法应该会起作用。您的销售模型取决于客户,因此您首先需要创建一个客户。然后,您的SellingProduct模型依赖于“产品和绘画”,因此您首先需要创建“产品和绘画”,然后创建具有以下实例的SellingProduct,例如:

class SellingSerializer():
    ...
    def create(self, validated_data):
        customer_data = validated_data.pop('customer')
        selling_products_data = validated_data.pop('products')

        customer = Customer.objects.create(**customer_data)
        selling = Selling.objects.create(customer=customer, **validated_data)

        for selling_product_data in selling_products_data :
            product_data = selling_product_data.pop('product')
            product = Product.objects.create(**product_data)

            painting_data = selling_product_data.pop('painting')
            painting = Painting.objects.create(**painting_data)

            SellingProducts.objects.create(selling=selling, product=product, painting=painting)

        return selling

当然,此方法会为每个请求创建一个新的客户,产品和绘画。这真的是您想要的吗?如果您不想为每个请求创建新的Product和Painting实例,而是使用对现有实例的引用,则可以在SellingSerializer和SellingProductSerializer中将它们定义为 PrimaryKeyRelatedField 字段。然后,您可以将create函数更改为此:

def create(self, validated_data):
    customer = validated_data.pop('customer')
    selling_products_data = validated_data.pop('products')

    selling = Selling.objects.create(customer=customer, **validated_data)

    for selling_product_data in selling_products_data :
        SellingProducts.objects.create(selling=selling, **selling_product_data )

    return selling

答案 1 :(得分:0)

您需要使用CustomerSerializer创建客户对象和数据库行,然后才能创建带有外键的Selling对象。您正在尝试不传递任何内容或传递JSON(在错误消息中变成OrderedDict)。

class SellingSerializer():
    ...
    def create(self, validated_data):
        customer_data = validated_data.pop('customer')
        products_data = validated_data.pop('products')
        customer = CustomerSerializer.save(**customer_data)
        selling = Selling.objects.create(customer=customer, **validated_data)
        for product_data in products_data:
            SellingProducts.objects.create(selling=selling, **product_data)
        return selling

也许在这个问题上重读了documentation

答案 2 :(得分:0)

  1. SellingSerializer与CustomerSerializerh,ProductSerializer相关

  2. 在创建Selling对象之前,我们可以验证每个序列化程序并创建

  3. 更新经过验证的数据

  4. 多对多过程

您将不仅仅是创建客户对象产品对象。数据必须经过验证,并且可以使用CustomerSerializer和ProductSerializer。在创建它们之前,先使用CustomerSerializer和ProductSerializer序列化数据,然后是有效的创建对象,否则引发异常。

class SellingSerializer():
    ...

    def create(self, validated_data):
        # First Let's handle Customer data
        customer_data = validated_data.pop('customer')
        customer_serializer = CustomerSerializer(data=customer_data)
        customer_serializer.is_valid(raise_exception=True)
        customer = customer_serializer.save()
        validated_data.update({'customer':customer})  ## update our validated data with customer instance

        # Create Selling object
        selling = Selling.objects.create(**validated_data)  # will receive customer instance as well

        # Handle Products related Data
        products_data = validated_data.pop('products')
        for product_data in products_data:
            product_serializer = ProductSerializer(data=product_data)
            product_serializer.is_valid(raise_exception=True)
            product = product_serializer.save()
            SellingProducts.objects.create(selling=selling, product=product)

        return selling