models.py
class Category(models.Model):
name = models.CharField(max_length=128)
class Product(models.Model):
category = models.ManyToManyField(Category, related_name="category")
name = models.CharField(max_length=128)
class ProductVariation(models.Model):
product = models.ForeignKey(Product, related_name="product")
name = models.CharField(max_length=128)
serializers.py
class ProductVariantSerializer(serializers.HyperlinkedModelSerializer)
class Meta:
model = ProductVariation
fields = (
"name",
)
class CategoryDetailSerializer(serializers.Modelserializer):
product_variant = PromotionVariantSerializer(many=True)
class Meta:
model = Category
fields =(
"name",
"product_variant" #how can i do this
)
here i want to list all the product variant that belongs to the category.
can i do this way or i want to write methods to get the product variant details
You may need to write serializers for Product and ProductVariation models. You can't display the ProductVariation objects right in the Category model serializer, as there is no direct relation between Category and ProductVariation models. But you could try may be using separate nested serializers for Product and ProductVariation models.
class ProductVariantSerializer(serializers.ModelSerializer):
class Meta:
model = ProductVariation
fields = ("name", )
class ProductSerializer(serializers.ModelSerializer):
variants = ProductVariantSerializer(source='product', many=True, read_only=True)
class Meta:
model = Product
fields = ('name', 'variants')
class CategorySerializer(serializers.ModelSerializer):
products = ProductSerializer(source='category', many=True, read_only=True)
class Meta:
model = Category
fields = ('name', 'products')
You could use the CategorySerializer for nested relationships.
Related
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = "__all__"
class EmployeeSerializer(serializers.ModelSerializer):
bookings_st = BookingSerializer(many=True, read_only=True)
class Meta:
model = Employee
fields = "__all__"
class ProjectSerializer(serializers.ModelSerializer):
employees = EmployeeSerializer(read_only=True, many=True)
class Meta:
model = Project
fields = "__all__"
class Employee(models.Model):
name = models.CharField(max_length=127)
lastname = models.CharField(max_length=127)
class Project(models.Model):
title = models.CharField(max_length=127)
employees = models.ManyToManyField(Employee,
related_name='employees')
class Booking(models.Model):
start = models.DateField()
end = models.DateField()
employee = models.ForeignKey(Employee,
on_delete=models.CASCADE,
related_name='bookings_st')
project = models.ForeignKey(Project,
on_delete=models.CASCADE,
related_name='bookings_st')
I get nested object, but how to get in Emploee only related to both (project and employee) bookings? Now I just get all bookings that this employee has.
I mean that structure:
project_1:
emploee_1:
[bookings_that_belong_to_THIS_PROJECT]
A possibility here is to leverage a SerializerMethodField together with the serializer's context object:
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = "__all__"
class EmployeeSerializer(serializers.ModelSerializer):
bookings_st = serializers.SerializerMethodField()
def get_bookings_st(self, employee):
project = self.context.get("project")
return BookingSerializer(
employee.bookings_st.filter(project=project),
many=True,
).data
class Meta:
model = Employee
fields = "__all__"
class ProjectSerializer(serializers.ModelSerializer):
employees = serializers.SerializerMethodField()
def get_employees(self, project):
return EmployeeSerializer(
project.employees.all(),
many=True,
context={**self.context, "project": project}
).data
class Meta:
model = Project
fields = "__all__"
This wouldn't be super performant if you're using that when listing projects or when retrieving a specific project with many employees. Depending on your use case - if you're only using it to retrieve a specific project, for example, you could leverage prefetch_related and the Prefetch class to prefetch custom employees + bookings querysets by filtering out the specific project at hand (and you could then use the regular serializers).
I have models:
class CommonEditor(models.Model):
def __str__(self):
return 'Common Atributes Mask'
class Color(models.Model):
name = models.CharField(max_length=25)
editor = models.ForeignKey(CommonEditor, on_delete=models.PROTECT, null=True)
So I make serialization this way:
class ColorSerializer(serializers.ModelSerializer):
class Meta:
model = Color
fields = '__all__'
class CommonAttributesSerializer(serializers.ModelSerializer):
color = ColorSerializer(many=True, read_only=True)
class Meta:
model = CommonEditor
fields = ('pk', 'color')
And then view:
class CommonAttributeAPIView(generics.ListCreateAPIView):
serializer_class = CommonAttributesSerializer
queryset = CommonEditor.objects.all()
I get only pk of my CommonEditor Model. Why can't i get the full Atributes Mask and how can I fix it? Big thanks!
Default name for reverse foreign key relation is modelname_set or in your case color_set. So try to rename color field to color_set:
class CommonAttributesSerializer(serializers.ModelSerializer):
color_set = ColorSerializer(many=True, read_only=True)
class Meta:
model = CommonEditor
fields = ('pk', 'color_set')
This can also be achieved via SerializerMethodField and can be seen as follow:
class CommonAttributesSerializer(serializers.ModelSerializer):
color = serializers.SerializerMethodField()
class Meta:
model = CommonEditor
fields = ('pk', 'color')
def get_color(self, common_editor):
return ColorSerializer(common_editor.color_set.all(), many=True).data
Documentation: http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
The CommonAttributesSerializer search for a color attribute in CommonEditor's instance, but it couldn't find. In DRF serializer, a parameter called source will says explicitly where to look for the data. So , change the serializer as below:
class CommonAttributesSerializer(serializers.ModelSerializer):
color = ColorSerializer(many=True, read_only=True, <b>source='color_set'</b>)
class Meta:
model = CommonEditor
fields = ('pk', 'color')
Reference : DRF Fields -source
I'm new to Django so I might miss the answer for this one because of terminology.
I am trying to get parent object with children objects, I've got:
#models.py
class Category(models.Model):
name = models.CharField(max_length=255)
sub_category = models.ForeignKey(SubCategory)
title = models.CharField(max_length=255, null=True)
#serializer.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
#views.py
Product.objects.all().filter(sub_category__category_id=category_id).select_related()
products_serializer = ProductSerializer(products, many=True)
return Response({
'data': products_serializer.data
})
I am trying to get parent category object within the children objects I've already got.
Thanks in advance :)
You already have your parent object, you can access it through each of your objects:
products = Product.objects.all().filter(sub_category__category_id=category_id)
for product in products:
parent = product.parent # You already have it
For better performance change your query to
Product.objects.all().filter(sub_category__category_id=category_id).select_related('parent')
As commented you can do it through serializers:
class ProductItemSerializer(serializers.ModelSerializer):
class Meta:
model = ProductItem
class ProductSerializer(serializers.ModelSerializer):
product_items = ProductItemSerializer(many=True, read_only=True)
class Meta:
model = Product
class CategorySerializer(serializers.ModelSerializer):
products = ProductSerializer(many=True, read_only=True)
class Meta:
model = Category
Now just get categories and products and items will be nested
I have two django models
model A
class A(models.Model):
aname = models.CharField(max_length=64, verbose_name='name')
and model B
class B(models.Model):
bname = models.CharField(max_length=64, verbose_name='name')
mod = models.ForeignKey(A, related_name='a_b',null=True,on_delete=models.CASCADE)
The serializer for model B is
class BSerializer(serializers.ModelSerializer):
mod= ASerializer(many=False, read_only=True)
class Meta:
model = B
fields = (','id','bname','mod.aname')
I want the aname field of model A to be accessed with the serializer of model B. Using mod.aname doesn't work. It says
Field name mod.aname is not valid for model B.
How can i do it?
How about this one? using parameter source inside serializers.CharField:
class BSerializer(serializers.ModelSerializer):
mod = serializers.CharField(
source='mod.aname',
read_only=True
)
class Meta:
model = B
fields = ('id','bname','mod')
Use two underscores when referencing fields of related models as a string, like 'mod__aname'.
class HotelSerializer(serializers.ModelSerializer):
mod= ASerializer(many=False, read_only=True)
class Meta:
model = Hotel
fields = ('id','bname','mod__aname')
This should work if ASerializer looks something like this:
class ASerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = '__all__'
Given the model and serializer classes below, when I retrieve Track details, it'll only show the Track title but not the related Artist.
How would I also show the Artist name when retrieving Track details?
models.py
class Artist (models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Track (models.Model):
artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Artist")
title = models.CharField(max_length=100, verbose_name="Title")
def __str__(self):
return self.title
serializers.py
class ArtistSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
name = serializers.CharField()
class Meta:
model = Artist
fields = ('id', 'name')
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = '__all__'
I think you need custom field, try this serializer:
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('title', 'artist','artist_name')
artist_name = serializers.SerializerMethodField('get_artists_name')
def get_artists_name(self, obj):
return obj.artist.name
It produce something like this.
[
{
"title": "Don't let me down",
"artist": 2,
"artist_name": "The Beatles"
},
{
"title": "Summertime",
"artist": 1,
"artist_name": "Ella Fitzgerald"
}
]
Try this serializer,
class ArtistSerializer(serializers.ModelSerializer):
class Meta:
model = Artist
fields = '__all__' # or array of fieldnames like ['name_1', 'name_2']
class TrackSerializer(serializers.ModelSerializer):
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('title', 'artist')
Inorder to retrieve Artist details, which is a ForeignKey model, you need to use a nested serializer in django-rest-framework.
By using the TrackSerializer with a nested ArtistSerializer, the retrieved data would look something like this,
{
"title": "Some_Title",
"artist": {
"id": 2, #or id of the artist.
"name": "Artist_name"
}
}
As you can see in the official django rest framework documentations
You should define a serializer field for nested items
First create your Artist (nested item) serializer
class ArtistSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
name = serializers.CharField()
class Meta:
model = Artist
fields = ('id', 'name')
Then you can use it on related model serializers
class TrackSerializer(serializers.ModelSerializer):
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('title', 'artist')
In the current version of DRF you can simply do this
class TrackSerializer(serializers.ModelSerializer):
artist = serializers.StringRelatedField()
class Meta:
model = Track
fields = '__all__'
StringRelatedField may be used to represent the target of the relationship using its __str__ method.
REF