Get full fields in nested model. Django Rest Framework - python

I have 2 model classes:
class CustomUser(AbstractUser):
username = models.CharField(max_length=30, unique=True)
tags = models.ManyToManyField('events.Tag', related_name='user_tag', blank=True)
class Tag(models.Model):
name = models.CharField(unique=True, max_length=50)
And serializers:
class UserSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
class Meta:
...
class TagSerializer(serializers.ModelSerializer):
class Meta:
lookup_field = 'name'
model = Tag
fields = ('id', 'name')
When I do a get query I get something like this:
"data": {
"type": "CustomUser",
"id": "6",
"attributes": {
"username": "mercer",
},
"relationships": {
"tags": {
"data": [
{
"type": "Tag",
"id": "1"
}
]
},
}
}
What I want is to get Tag 'name' field in user representation:
"type": "Tag",
"id": "1",
"name":"name"
And I want to make patch query for adding tag to user.
I can use SerializerMethodField(), but this way I will not able to add tags

The problem was with settings of rest framework. I wrote there custom json render classes and recived this form of output. Now i removed it and everything is fine.

Related

how join 3 table in Django Python

This is my first class
class dot_bay(models.Model):
ma_dot_bay = models.CharField(primary_key=True,max_length=255, default=uuid.uuid4, editable=False)
ten_dot_bay = models.CharField(max_length=255, default="")
ngay_bay = models.DateTimeField()```
This is my second class
class video(models.Model):
ma_video = models.CharField(primary_key=True, max_length=255, default=uuid.uuid4, editable=False)
ma_dot_bay = models.ForeignKey(dot_bay, on_delete=models.CASCADE, related_name='dot_bay_video')
video_path = models.TextField()
detected_path = models.TextField()
ngay_upload = models.TextField()
And my third class
class hinh_anh(models.Model):
ma_hinh_anh = models.CharField(primary_key=True, max_length=255, default=uuid.uuid4, editable=False)
ma_video = models.ForeignKey(video, on_delete=models.CASCADE, related_name='video_hinh_anh')
image_base64 = models.TextField()
I try this in my Serializer in my project to display result of 2 join table dot_bay and video
like that
class DotBayModelSerializer(serializers.ModelSerializer):
class Meta:
model = dot_bay
fields = ("ma_dot_bay", "ten_dot_bay", "ngay_bay", "dot_bay_video")
depth = 1
And get the result like that
[
{
"ma_dot_bay": "db0001",
"ten_dot_bay": "Đợt bay",
"ngay_bay": "2021-05-14T15:30:27Z",
"dot_bay_video": [
{
"ma_video": "vd0001",
"video_path": "1",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0001"
},
{
"ma_video": "vd0002",
"video_path": "1",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0001"
}
]
},
{
"ma_dot_bay": "db0002",
"ten_dot_bay": "Đợt bay",
"ngay_bay": "2021-05-14T15:31:07Z",
"dot_bay_video": [
{
"ma_video": "vd0003",
"video_path": "1",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0002"
},
{
"ma_video": "vd0004",
"video_path": "11",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0002"
}
]
}
]
that's what I expected
But now I want to join 3 table, display like that,
[
{
"ma_dot_bay": "db0002",
"ten_dot_bay": "Đợt bay",
"ngay_bay": "2021-05-14T15:31:07Z",
"dot_bay_video": [
{
"ma_video": "vd0003",
"video_path": "1",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0002",
"video_hinh_anh": [
{
"ma_hinh_anh": "....."
},
{
"ma_hinh_anh": "....."
}
]
},
{
"ma_video": "vd0004",
"video_path": "11",
"detected_path": "1",
"ngay_upload": "1",
"ma_dot_bay": "db0002",
"video_hinh_anh": [
{
"ma_hinh_anh": "....."
},
{
"ma_hinh_anh": "....."
}
]
}
]
}
]
I try some method but not working :((((
How can I do that ??
The idea here is to use nested serializers. In our case, we'll use those nested serializers to detail how we want foreign key objects to be rendered/structure.
Try something like that:
class NestedHinhAnhModelSerializer(serializers.ModelSerializer):
class Meta:
model = hinh_anh
# Didnt put the `ma_video` field since we're using this serializer inside a video model
fields = ("ma_hinh_anh ", "image_base_64")
class NestedVideoModelSerializer(serializers.ModelSerializer):
# We override the `video_hinh_anh` field with a custom serializer
video_hinh_anh = NestedHinhAnhModelSerializer(many=True)
class Meta:
model = video
# I didnt put the `ma_dot_bay` fk field since we'll be using this serializer inside the dot_bay model
fields = ("ma_video ", "video_path ", "detected_path ", "ngay_upload", "video_hinh_anh")
class NestedVideoModelSerializer(serializers.ModelSerializer):
# We override the `dot_bay_video` with a custom serializer
dot_bay_video = VideoModelSerializer(many=True)
class Meta:
model = dot_bay
fields = ("ma_dot_bay", "ten_dot_bay", "ngay_bay", "dot_bay_video")

How to sort source argument for nested serializer field in Django REST Framework?

I have 2 models: Page and Section. A Page object may have 1-to-many Section objects.
In models.py:
class Page(models.Model):
name = models.CharField(max_length=100, help_text='Name of the page.')
class Meta:
ordering = ['id']
class Section(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE)
name = models.CharField(max_length=100, help_text='Name of the section.')
index = models.IntegerField(blank=True, help_text='Index number to sort section.')
class Meta:
ordering = ['id']
index in a Section object indicates its ordering (position) among the rest of Section objects that have same Page object as their foreign key.
In serializers.py:
class SectionSerializer(serializers.ModelSerializer):
page = serializers.PrimaryKeyRelatedField(queryset=Page.objects.all(),
many=False, required=True)
class Meta:
model = Section
fields = ['id', 'page', 'name', 'index']
class PageSerializer(serializers.ModelSerializer):
sections = SectionSerializer(source='section_set', many=True, required=False) # problem is here.
# can I do something like source="section_set.order_by('index')"
class Meta:
model = Page
fields = ['id', 'name', 'sections']
With sections attribute in PageSerializer I can get all Section objects that have the same Page object as foreign key. But not ordered by their index field.
When I query Page.objects.all using PageSerializer I got this result in browsable API:
[
{
"id":1,
"name":"Home",
"sections":[
{
"id":10,
"page":1,
"name":"second_section_for_page_1",
"index":2
},
{
"id":11,
"page":1,
"name":"first_section_for_page_1",
"index":1
},
{
"id":12,
"page":1,
"name":"third_section_for_page_1",
"index":3
}
]
},
{
"id":2,
"name":"Profile",
"sections":[
{
"id":13,
"page":2,
"name":"second_section_for_page_2",
"index":2
},
{
"id":14,
"page":2,
"name":"first_section_for_page_2",
"index":1
}
]
}
]
I would like the result to be ordered by index. Like this:
[
{
"id":1,
"name":"Home",
"sections":[
{
"id":11,
"page":1,
"name":"first_section_for_page_1",
"index":1
},
{
"id":10,
"page":1,
"name":"second_section_for_page_1",
"index":2
},
{
"id":12,
"page":1,
"name":"third_section_for_page_1",
"index":3
}
]
},
{
"id":2,
"name":"Profile",
"sections":[
{
"id":14,
"page":2,
"name":"first_section_for_page_2",
"index":1
},
{
"id":13,
"page":2,
"name":"second_section_for_page_2",
"index":2
}
]
}
]
Can I do something like sections = SectionSerializer(source="section_set.order_by('index')") in PageSerializer class?

how to create multiple objects with one request DRF

I have the following models
class Product(models.Model):
name = models.CharField(null=True, blank=True, max_length=500)
category = models.CharField(null=True, blank=True, max_length=120)
class SpecificationName(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True, related_name='specifications')
name = models.CharField(max_length=125)
class Attribute(models.Model):
spec_name = models.ForeignKey(SpecificationName, on_delete=models.CASCADE, null=True, related_name='attributes')
index = models.CharField(max_length=200, blank=True, null=True)
value = models.CharField(max_length=250, blank=True, null=True)
after saving objects in Django admin I have an example
{
"name": "Apple Smart Watch",
"category": "IT",
"specifications": [
{
"name": "Test Data",
"attributes": [
{
"index": "test",
"value": "test2"
},
{
"index": "test7",
"value": "test8"
},
{
"index": "test9",
"value": "test10"
}
]
},
{
"name": "Test Data Continued",
"attributes": [
{
"index": "bla",
"value": "bla1"
},
{
"index": "bla 2",
"value": "bla 4"
},
{
"index": "test9",
"value": "test10"
}
]
},
{
"name": "Test Spec",
"attributes": []
}
]
}
I need to save this kind of object with one request but I am failing to do this
my serializer looks like this
class ProductSerializer(serializers.ModelSerializer):
specifications = SpecNameSerializer(many=True)
# attributes = AttributeSerializer(many=True, required=False)
class Meta:
model = Product
fields = ['name', 'category', 'brand', 'price', 'specifications']
def create(self, validated_data):
specs = validated_data.pop('specifications')
instance = Product.objects.create(**validated_data)
for spec in specs:
SpecificationName.objects.create(product=instance, **spec)
print(spec)
return instance
with this code, I am getting the following result but not as expected
{
"name": "Appel watch series",
"specifications": [
{
"name": "Test Data",
"attributes": []
},
{
"name": "Test Data comn",
"attributes": []
},
{
"name": "Test Spec",
"attributes": []
}
]
}
it cannot write into attributes
I searched for many answers but I did not find or applied some of them, again it did not help me. I am using just ListCreateView in the views. Please is there anybody who can help solve this problem. Thanks in advance!
SOLVED
I am using here ModelSerializer instead I used Serializer and added some changes here my answer and it worked
class AttributeSerializer(serializers.Serializer):
index = serializers.CharField(max_length=200)
value = serializers.CharField(max_length=200)
class SpecNameSerializer(serializers.ModelSerializer):
attributes = AttributeSerializer(many=True)
class Meta:
model = SpecificationName
fields = '__all__'
class ProductSerializer(serializers.ModelSerializer):
specifications = SpecNameSerializer(many=True)
class Meta:
model = Product
fields = ['name', 'category', 'brand', 'price', 'specifications']
def create(self, validated_data):
specs = validated_data.pop('specifications')
instance = Product.objects.create(**validated_data)
for spec in specs:
SpecificationName.objects.create(product=instance, **spec)
attrs = spec.pop('attributes')
for attr in attrs:
Attribute.objects.create(spec_name=spec, **attr)
return instance

Django Rest Framework: Get related specific model field in serializer from another model

I'm trying to return a Response including data from 2 linked models, where I can get a specific field value from another model. The models are:
class Author(models.Model):
author = models.CharField(max_length=200)
author_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('author_created',)
class Book(models.Model):
book_name = models.CharField(max_length=200)
author_name = models.ForeignKey(Author, on_delete=models.CASCADE)
book_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('book_created',)
Serializers are:
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ('id', 'author')
class BookSerializer(serializers.ModelSerializer):
name = AuthorSerializer(source='author_name')
class Meta:
model = Book
fields = ('id', 'book_name','name')
My response shows like this:
[
{
"id": 1,
"book_name": "Himu",
"name": {
"id": 1,
"author": "Humayun Ahmed"
}
},
{
"id": 2,
"book_name": "Shanta's family",
"name": {
"id": 2,
"author": "Jafar Iqbal"
}
}
]
But i want to show it like this:
[
{
"id": 1,
"book_name": "Himu",
"name": {
"author": "Humayun Ahmed"
}
},
{
"id": 2,
"book_name": "Shanta's family",
"name": {
"author": "Jafar Iqbal"
}
}
]
How can i get this output?
Try something like this name = AuthorSerializer(source='author_name.author')
Reference : http://www.django-rest-framework.org/api-guide/fields/#source

Django REST - How to create a non-model serializer?

Firstly I want to say I'm a newbie to Django.
I was wondering if is it possible to create a non-ModelSerializer which serialize existant model based serializers ?
In serializers.py, I already have this :
class MapSerializer(serializers.ModelSerializer):
class Meta:
model = Map
fields = ('id', 'name')
class GrenadeSerializer(serializers.ModelSerializer):
class Meta:
model = Grenade
fields = ('id', 'name')
I want here a new serializer which allows to display a JSON like that :
{
"maps": {
"map": [
{
"id": "1",
"name": "dust2"
},
{
"id": "2",
"name": "inferno"
}
]
},
"grenades": {
"grenade": [
{
"id": "1",
"name": "flashbang"
},
{
"id": "2",
"name": "smoke"
}
]
}}
I need something like this, even if I know the following structure isn't correct :
class MyNewSerializer(serializers.ModelSerializer):
maps = MapSerializer(many=True)
grenades = GrenadeSerializer(many=True)
class Meta:
field = ('maps', 'grenades')
Thanks in advance !

Categories