I want to nest a model into the serializer. Like on list of Category, there should be fields from Brand model, But I m getting error by on setting this way ?
models.py
class Category(models.Model):
title = models.CharField(max_length=50)
timestamp = models.DateTimeField(auto_now_add=True)
#....
class Brand(models.Model):
title = models.CharField(max_length=50)
category = models.ForeignKey(
Category, blank=True, null=True, on_delete=models.SET_NULL, related_name="category")
#....
Serializers
class CategorySerializerNested(serializers.ModelSerializer):
brands = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Category
fields = '__all__'
def get_brands(self, obj):
brands = obj.brand_set.all() #this thin popping error how to fix that....
serializer = BrandSerializerNested(brands, many=True)
return serializer.data
class BrandSerializerNested(serializers.ModelSerializer):
products = serializers.SerializerMethodField(read_only=True)
def get_products(self, obj):
products = obj.product_set.all()
serializer = ProductSerializer(products, many=True)
return serializer.data
class Meta:
model = Brand
fields = '__all__'
View.py
@api_view(['GET'])
def getCategoryWithBrands(request, pk):
category = Category.objects.get(id=pk)
serializer = CategorySerializerNested(category, many=False)
return Response(serializer.data)
url.py
path('nested/<str:pk>/', views.getCategoryWithBrands,
name="category-with-brands"),
Error:
AttributeError: 'Category' object has no attribute 'brand_set'
[02/Feb/2022 03:24:49] "GET /api/v1/categories/nested/1/ HTTP/1.1" 500 125121
I’m sure im doing something illogical but i dont know now, please help me to fix this , if there’s any better way to do that please also help there as well. Thanks
>Solution :
Since you specified related_name='category'
, you obtain the related Brand
s with:
def get_brands(self, obj):
brands = obj.category.all()
serializer = BrandSerializerNested(brands, many=True)
return serializer.data
But that does not make much sense: the related_name=…
[Django-doc] specifies the name of the relation in reverse so obtaining the Brand
s for a given Category
, you thus can rename these to:
class Brand(models.Model):
category = models.ForeignKey(
Category,
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='brands'
)
#…
and work with a subserializer:
def get_brands(self, obj):
brands = obj.brands.all()
serializer = BrandSerializerNested(brands, many=True)
return serializer.data
or just define BrandSerializerNested
first and use:
class CategorySerializerNested(serializers.ModelSerializer):
brands = serializers.BrandSerializerNested(read_only=True)
class Meta:
model = Category
fields = '__all__'