Why i can't to update nested serializer by id? - python

When i send data throw PUT request this id can't get this id in validated data.
For example body of PUT request:
{
"slug": "string",
"company_id": 1,
"api_secret": "string",
"merchant_url_list": [
{
"id": 1
"merchant_url_type_id": 1,
"url": "string"
}
]
}
But in validated_data {'slug': 'string', 'company': <Company: Company object (1)>, 'api_secret': 'string', 'merchanturl_set': [OrderedDict([('merchant_url_type', <MerchantUrlType: Бот (None)>), ('url', 'string')])]}
There is not id. How i can get id?
class MerchantUrlSerializer(IdModelSerializer):
merchant = serializers.PrimaryKeyRelatedField(required=False, read_only=True)
class Meta:
model = MerchantUrl
fields = ('id', 'merchant_url_type', 'merchant', 'url')
class MerchantSerializer(NestedSerializerMixin, IdModelSerializer):
merchant_url_list = MerchantUrlSerializer(source='merchanturl_set', many=True)
class Meta:
model = Merchant
fields = ('id', 'slug', 'company', 'api_secret', 'merchant_url_list')
{
"slug": "string",
"company_id": 0,
"api_secret": "string",
"merchant_url_list": [
{
"merchant_url_type_id": 0,
"url": "string"
}
]
}

The pk field - id in your case - is read_only by default since it represents the PK.
If you want to alter that behaviour, you'll need to set it read/write:
class MerchantUrlSerializer(IdModelSerializer):
merchant = serializers.PrimaryKeyRelatedField(required=False, read_only=True)
class Meta:
model = MerchantUrl
fields = ('id', 'merchant_url_type', 'merchant', 'url')
extra_kwargs = {'id': {'read_only': False}}

Related

Django : This field is required on POST request

I'm trying to create a serializer which outputs the Report and also the User information.
My task is accomplished by this serializer:
class ReportSerializer(serializers.ModelSerializer):
latitude = serializers.CharField()
longitude = serializers.CharField()
city = serializers.IntegerField()
type = serializers.IntegerField()
# We have created a field which returns a value from get_marker_icon_url
marker_icon = serializers.SerializerMethodField('get_marker_icon_url')
status_str = serializers.SerializerMethodField('convert_status_toStr')
type_str = serializers.SerializerMethodField('convert_type_toStr')
status_color = serializers.SerializerMethodField('get_status_color')
likes = serializers.SerializerMethodField('random_likes')
user = ReportUserSerializer()
class Meta:
model = Reports
fields = [
'user',
'id',
'type',
'city',
'latitude',
'longitude',
'likes',
'type_str',
'status_str',
'status_color',
'attached_message',
'marker_icon',
'attached_photo',
'date_created'
]
...
With this code my serializer returns a response like this:
[
{
"user": {
"id": 1,
"username": "3nematix",
"profile_pic": "http://192.168.0.29:8000/frontend/static/frontend/images/reports/user_profile_pic.jpg",
"verified": false
},
"id": 1,
"type": 9,
"city": 0,
"latitude": "6.5123333",
"longitude": "51.512586",
"likes": 27,
"type_str": "OTHER",
"status_str": "PENDING",
"status_color": "orange",
"attached_message": "test",
"marker_icon": "OTHER",
"attached_photo": "http://192.168.0.29:8000/frontend/static/frontend/images/reports/user_profile_pic_VRjIYTs.jpg",
"date_created": "2020-10-21T23:19:06.899302Z"
},
......
]
And this is exactly what I need, but the problem is that when I'm trying to create a new object by a POST request, I get this response:
{
"user": [
"This field is required."
]
}
If I would remove 'user' from Meta and user = ReportUserSerializer() from the ReportSerializer class, then I can create a new object, but when I wish to get the Reports I with the Users information I need to add these two again, how can I fix it?
You need to fill the user field yourself before calling save.
Here's the easy way:
class YourView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.save(user=self.request.user)
Or slightly differently:
class YourView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.validated_data['user'] = self.request.user
return super().perform_create(serializer)

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?

Source field in DRF serializer with multiple foreign keys to the same model

I have a Django model as follows:
class Team(models.Model):
name = models.CharField(max_length=100, unique=True)
managers = models.ManyToManyField(User, through=MgrToTeam, related_name='mng')
users = models.ManyToManyField(User, through=UsrToTeam,related_name='usr')
I now have a serializer where i need to display all the users and managers associated with a team:
class TeamDetailSerializer(serializers.ModelSerializer):
managers = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='name')
users = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='name')
class Meta:
model = Team
fields = ['id', 'name', 'managers', 'users']
However, this gives me the same output for both the users and managers.How do i fix this ?
I'm curious as to why you want to use a SlugRelatedField. Assuming you do have a UserSerializer of some sort, would it work for you to do it like this?
class TeamDetailSerializer(serializers.ModelSerializer):
managers = UserSerializer(many=True)
users = UserSerializer(many=True)
class Meta:
model = Team
fields = ['id', 'name', 'managers', 'users']
if you just want Just primary key as below
[
{
"id": 1,
"name": "helo",
"users": [
1,
2
],
"managers":[
1,
2,
]
}
]
class TeamDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = ['id', 'name', 'users','managers']
if you want return object properties as below
[
{
"id": 1,
"name": "helo",
"users": [
{
"email": "admin#gmail.com",
"first_name": ""
},
{
"email": "admin1#gmail.com",
"first_name": ""
}
],
"managers": [
{
"email": "admin#gmail.com",
"first_name": ""
},
{
"email": "admin1#gmail.com",
"first_name": ""
}
]
}
]
class TeamDetailSerializer(serializers.ModelSerializer):
users = UserDetailSerializer(many=True)
managers = UserDetailSerializer(many=True)
class Meta:
model = Team
fields = ['id', 'name', 'users', 'managers']

Django DRF list of ids object

I have such serializers
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id',)
class MyModelIdListSerializer(serializers.Serializer):
ids = MyModelSerializer(many=True)
And request body like
{
"ids": [
{
"id": "f07e3673-6631-4139-90da-331773ba868e"
},
{
"id": "f07e3673-6631-4139-90da-331773ba868e"
}
]
}
But need this
{
"ids": [
"f07e3673-6631-4139-90da-331773ba868e",
"f07e3673-6631-4139-90da-331773ba868e"
]
}
I can do ListField with UUID as child but need to write custom validate if such id exists on table
If you want list of ids use PrimaryKeyRelatedField
ids = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

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

Categories