У меня есть две родственные модели: Product
и ProductDescription
. В 1 отправке действие пользователь может вставить новый Product
с несколькими описаниями в зависимости от доступных языков. Я использую записываемый вложенный сериализатор для одновременной вставки в Product
и ProductDescription
. Я делаю это, переопределяя функцию create
в классе ProductDescriptionSerializer
, это работает. Однако я могу вставить только 1 ProductDescription
за раз.
Затем я попытался использовать этот ответ , чтобы создать несколько экземпляров модели одновременно. Проблема заключается в том, что он также создает один и тот же Product
дважды вместо использования вновь созданного Product
Id для вставки следующего ProductDescription
.
My models.py
:
class Product(models.Model, ProductStatus):
product_code = models.CharField(max_length=6)
color = models.ForeignKey(ColorParent, on_delete=models.SET_NULL, null=True)
collection = models.ForeignKey(ProductCollection, on_delete=models.SET_NULL, null=True)
video = models.URLField(verbose_name='Video URL', max_length=250, null=True, blank=True)
status = models.CharField(max_length=20, choices=ProductStatus.status, default=ProductStatus.active)
class ProductDescription(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
language = models.ForeignKey(Language, on_delete=models.CASCADE)
description = models.TextField(max_length=500, null=True, blank=True)
def __str__(self):
return '%s - %s' % (self.product, self.language)
My serializers.py
:
class CustomRelatedField(serializers.RelatedField):
def display_value(self, instance):
return instance
def to_representation(self, value):
return str(value)
def to_internal_value(self, data):
model = self.queryset.model
return model.objects.get(id=data)
class ProductSerializer(serializers.ModelSerializer):
collection = CustomRelatedField(queryset=ProductCollection.objects.all(), many=False)
color = CustomRelatedField(queryset=ColorParent.objects.all(), many=False)
class Meta:
model = Product
fields = ['id', 'product_code', 'collection', 'color', 'video', 'status']
class ProductDescriptionSerializer(serializers.ModelSerializer):
product = ProductSerializer()
language = CustomRelatedField(many=False, queryset=Language.objects.all())
class Meta:
model = ProductDescription
fields = ['id', 'product', 'language', 'description']
def to_representation(self, instance):
data = super().to_representation(instance)
if self.context['request'].method == 'GET':
data['product'] = instance.product.product_code
return data
return Serializer.to_representation(self, instance)
# The `.create()` method does not support writable nested fields by default.
def create(self, validated_data):
# create product data for Product model.
product_data = validated_data.pop('product')
product = Product.objects.create(**product_data)
# create ProductDescription and set product FK.
product_description = ProductDescription.objects.create(product=product, **validated_data)
# return ProductDescription instance.
return product_description
My views.py
:
class CreateListModelMixin(object):
def get_serializer(self, *args, **kwargs):
if isinstance(kwargs.get('data', {}), list):
kwargs['many'] = True
return super(CreateListModelMixin, self).get_serializer(*args, **kwargs)
class ProductDescriptionView(CreateListModelMixin, viewsets.ModelViewSet):
permission_classes = [permissions.DjangoModelPermissions]
queryset = ProductDescription.objects.all()
serializer_class = ProductDescriptionSerializer
http_method_names = ['get', 'head', 'post', 'put', 'patch', 'delete']
Формат JSON, который я использую для POST-данных:
[
{
"product": {
"product_code": "BQ1080",
"collection": 5,
"color": 7,
"video": "https://www.youtube.com/watch?v=",
"status": "Continue"
},
"language": 1,
"description": "English description."
},
{
"product": {
"product_code": "BQ1080",
"collection": 5,
"color": 7,
"video": "https://www.youtube.com/watch?v=",
"status": "Continue"
},
"language": 2,
"description": "Vietnamese description."
}
]
Создает дубликат Product
в списке товаров:
[
{
"id": 26,
"product_code": "BQ1080",
"collection": 5,
"color": 7,
"video": "https://www.youtube.com/watch?v=",
"status": "Continue"
},
{
"id": 27,
"product_code": "BQ1080",
"collection": 5,
"color": 7,
"video": "https://www.youtube.com/watch?v=",
"status": "Continue"
}
]
Данные ProductDescription
верны, хотя:
[
{
"id": 5,
"product": "BQ1080",
"language": "English",
"description": "English description."
},
{
"id": 6,
"product": "BQ1080",
"language": "Vietnam",
"description": "Vietnamese description."
}
]