Django Rest Framework |Записываемые множественные вложенные отношения - PullRequest
1 голос
/ 15 марта 2019

У меня есть несколько моделей, и они вложены друг в друга.Я хочу сделать массовое создание для 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.Как я могу это сделать также?

Я хочу создать запись для Продажи и Продажи продукта, Живописи, и я НЕ хочу создавать записи о клиенте, адресе, продукте в каждом запросе, и я буду использовать существование(в выбранном интерфейсе).

Спасибо всем заранее за любую помощь!

Ответы [ 3 ]

2 голосов
/ 15 марта 2019

Ваш первый подход должен работать, если вы сделаете несколько изменений. Ваша модель продажи зависит от клиента, поэтому сначала вам нужно создать клиента. Затем ваша модель 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 для каждого запроса, но используете ссылки на существующие экземпляры, вы можете определить их как поля PrimaryKeyRelatedField в SellingSerializer и SellingProductSerializer. Затем вы можете изменить функцию создания следующим образом:

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
0 голосов
/ 16 марта 2019
  1. SellingSerializer связан с CustomerSerializerh, ProductSerializer

  2. Перед созданием объекта продажи мы можем проверить каждый сериализатор и создать

  3. обновить проверенные данные

  4. процесс много ко многим

Вы бы не просто создавали объект продукта объекта клиента. Данные имеютбыть проверенным и может использовать CustomerSerializer и ProductSerializer.Перед их созданием сериализуйте ваши данные с помощью CustomerSerializer и ProductSerializer, затем действительный объект create, иначе вызовите исключение.

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
0 голосов
/ 16 марта 2019

Вам необходимо использовать 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

Возможно, перечитайте документацию по этому вопросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...