I have a product model like this:
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(blank=True, null=True)
category = models.ForeignKey(ProductCategories, on_delete=models.CASCADE)
brand = models.ForeignKey(ProductBrand, on_delete=models.SET_NULL, blank=True, null=True)
score = models.PositiveIntegerField(blank=True, null=True)
insurnace = models.PositiveIntegerField(blank=True, null=True)
property = models.ManyToManyField(ProductProperty, blank=True)
is_flagship = models.BooleanField(default=False)
is_exhibition = models.BooleanField(default=False)
seen = models.IntegerField(default=0)
for saving images, prices and details i wrote this three model:
class ProductImage(models.Model):
image = models.ImageField(upload_to='product_image/')
product = models.ForeignKey(Product, related_name='image', on_delete=models.SET_NULL, blank=True, null=True)
is_main_image = models.BooleanField(default=False)
class ProductDetail(models.Model):
title = models.ForeignKey(ProductDetailTitle, related_name='value', on_delete=models.CASCADE)
value = models.CharField(max_length=500)
product = models.ForeignKey(Product, related_name='detail', on_delete=models.CASCADE)
class ProductPrice(models.Model):
product = models.ForeignKey(Product, related_name='price', on_delete=models.CASCADE)
color = models.ForeignKey(ProductColor, on_delete=models.CASCADE)
price = models.PositiveIntegerField()
quantity = models.PositiveIntegerField()
i wrote this serializer for manage product
class ProductAdminSerializer(serializers.ModelSerializer):
images = serializers.ListSerializer(child=serializers.IntegerField())
prices = ProductPriceForProductAdminSerializer(many=True)
properties = serializers.ListSerializer(child=serializers.IntegerField())
details = ProductDetailForProductAdminSerializer(many=True)
class Meta:
model = Product
fields = ['id', 'title', 'category', 'brand', 'images', 'description', 'properties', 'is_flagship',
'is_exhibition', 'prices', 'score', 'insurnace', 'details']
def create(self, validated_data):
title = validated_data.get('title')
category = validated_data.get('category')
brand = validated_data.get('brand')
description = validated_data.get('description')
is_flagship = validated_data.get('is_flagship')
is_exhibition = validated_data.get('is_exhibition')
score = validated_data.get('score')
insurnace = validated_data.get('insurnace')
product = Product.objects.create(title=title, category=category, brand=brand,
description=description, is_flagship=is_flagship, is_exhibition=is_exhibition,
score=score, insurnace=insurnace)
image_ids = validated_data.get('images')
ProductImage.objects.filter(id__in=image_ids).update(product=product)
properties = validated_data.get('properties')
if properties is not None:
property_objs = ProductProperty.objects.filter(id__in=properties)
product.property.set(property_objs)
prices = validated_data.get('prices')
if prices is not None:
prices_obj = list()
for price_obj in prices:
color = price_obj.get('color')
price = price_obj.get('price')
quantity = price_obj.get('quantity')
prices_obj.append(ProductPrice(product=product, color=color, price=price, quantity=quantity))
ProductPrice.objects.bulk_create(prices_obj)
details = validated_data.get('details')
if details is not None:
details_obj = list()
for detail in details:
title = detail.get('title')
value = detail.get('value')
details_obj.append(ProductDetail(product=product, title=title, value=value))
ProductDetail.objects.bulk_create(details_obj)
return validated_data
def update(self, instance, validated_data):
images = validated_data.pop('images', None)
properties = validated_data.pop('properties', None)
prices = validated_data.pop('prices', None)
details = validated_data.pop('details', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
if images is not None:
ProductImage.objects.filter(product=instance).exclude(id__in=images).delete()
ProductImage.objects.filter(id__in=images).update(product=instance)
if properties is not None:
property_objs = ProductProperty.objects.filter(id__in=properties)
instance.property.set(property_objs)
return instance
the create method is ok and work well. my problem is with update after send patch request, everything in database getting update as should, but at the end i get this error
AttributeError: Got AttributeError when attempting to get a value for field
images
on serializerProductAdminSerializer
. The serializer field might be named incorrectly and not match any attribute or key on theProduct
instance. Original exception text was: 'Product' object has no attribute 'images'.
how can I fix that?
You have a field images
on the serializer, but not on the Product model.
To serialize your instance, the serializer try to find a field named "images" on the model, which leads to this error.
A solution could be to use the field "images" only for saving objects with write_only
class ProductAdminSerializer(serializers.ModelSerializer):
images = serializers.ListSerializer(child=serializers.IntegerField(), write_only=True)
If you need the list of the images in the response, you can create another field with read_only.