I am using generics to represent views
class PersonRetrieveView(generics.ListAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
and
class CommentRetrieveView(generics.RetrieveAPIView):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
Person data looks like
{
"id": 2,
"user": {
"first_name": "Testuser",
"last_name": "TestUser1",
"id": 2
},
"name": "Test 2",
"city": "California",
"status": "NotActive",
"phone_number": "9876543222",
"age": 22,
"height": 180
}
and Comment
{
"id": 1,
"comment": "test",
"person": 2
}
Comment linked to Person by id. How can i add data from comment to PersonRetrieveView ?
Serializers looks like this
class PersonSerializer(serializers.ModelSerializer):
user = UserSerializer()
# comment = CommentSerializer()
class Meta:
model = Person
fields = '__all__'
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
Model looks like
class Person(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
city = models.CharField(max_length=20)
status = models.CharField(max_length=9, default='NotActive')
phone_number = models.CharField(max_length=10)
class Comment(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
comment = models.CharField(max_length=255)
You have Many-to-one relationship and you did not set related_name on Foreign key so your comments are accessible through comment_set which can be used to nest serializer
class PersonSerializer(serializers.ModelSerializer):
user = UserSerializer()
comments = CommentSerializer(source='comment_set', many=True)
class Meta:
model = Person
fields = [ 'user', 'city', 'comments', ...]
Provided that your Person model has a relation to Comment models, simply add depth = 1 in your Person serializer as follows:
class PersonSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Person
fields = '__all__'
depth = 1
Related
class Hotel (models.Model):
name = models.CharField()
country = models.CharField()
city = models.CharField()
street = models.CharField()
class Residence(models.Model):
hotel_id = models.ForeignKey(Hotel, on_delete=models.DO_NOTHING, related_name='hotel')
house_number = models.CharField()
I want to join two models (Hotel and Residence) and then post it. I wrote the folowing code:
serializers.py
class HotelSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Hotel
fields = ['name', 'country', 'city', 'street']
class ResidenceSerializer(serializers.HyperlinkedModelSerializer):
hotel_id = HotelSerializer()
class Meta:
model = Residence
fields = ['house_number', 'hotel_id']
def create(self, validated_data):
return Residence.objects.create(**validated_data)
views.py
class ResidenceViewSet(viewsets.ModelViewSet):
serializer_class = ResidenceSerializer
queryset = Residence.objects.all()
When I try to post data in my api I got the following error: Residence() got an unexpected keyword argument 'hotel_id'. Can someone help me?
Replacing hotel_id with hotel. And still, you can pass hotel from view
class ResidenceSerializer(serializers.HyperlinkedModelSerializer):
hotel = HotelSerializer()
class Meta:
model = Residence
fields = ['house_number', 'hotel']
Also if you are not interested in hyper links(urls) then replace
`serializers.HyperlinkedModelSerializer` with `serializers.ModelSerializer`.
Difference between HyperlinkedModelSerializer and ModelSerializer is serializer is posted here by Serjik
A simple example:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'groups')
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ('url', 'name')
bash> http -a admin:yourpassword http://127.0.0.1:8000/users/
"results": [
{
"email": "admin#min.com",
"groups": [
"http://127.0.0.1:8000/groups/1/",
"http://127.0.0.1:8000/groups/2/"
],
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin"
}
]
But if you change
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'groups')
The result will be:
"results": [
{
"email": "admin#min.com",
"groups": [
1,
2
],
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin"
}
]
I want to retrieve Student user fields, but I am having a hard time
trying to figure out how to do that I tried reading docs but still
confused
Studentserializer
class StudentSerializer(serializers.Serializer):
class Meta:
model = Student
fields = ['id', 'user', 'name', 'course']
def create(self, validated_data):
Student_det = Student.objects.create(**validated_data)
return Student_det
serializer view
def Student_list(request):
if request.method == 'GET':
stud = Student.objects.all()
serialized = StudentSerializer(stud, many=True)
print(serialized.data)
return JsonResponse(serialized.data, safe=False)
Student Model
class Student (models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
course = models.CharField(max_length=255)
You can check here. I think the part about nested serializers is what you need.
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("id", "first_name", "last_name", ) # and you can add other fields here "email", "date_joined", etc.
class StudentSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Student
fields = ("id", "user", "name", "course", )
This will serialize your Student model like
{
"id": 1,
"user": {
"id": 1,
"first_name": "Example",
"last_name": "User"
}
"name": "student name",
"course": "course name"
}
I have 2 models connected via M2M model:
class Person(models.Model):
name = models.CharField(max_length=30)
class Group(models.Model):
name = models.CharField(max_length=100)
members = models.ManyToManyField(Person, through='GroupPerson', related_name='groups')
class GroupPerson(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
rank = models.CharField(max_length=100', default='New')
and serializers
class GroupPersonSerializer(serializers.ModelSerializer):
class Meta:
model = GroupPerson
fields = '__all__'
class GroupSerializer(serializers.ModelSerializer):
members = serializers.PrimaryKeyRelatedField(many=True, queryset=Person.objects.all())
class Meta:
model = Group
fields = '__all__'
class PersonSerializer(serializers.ModelSerializer):
groups = serializers.PrimaryKeyRelatedField(many=True, queryset=Group.objects.all())
class Meta:
model = Person
fields = '__all__'
And API go get a group returns
[
{
"name": "...",
"members": [ 1, ... ]
}
]
How do I get a response something like following:
[
{
"name": "...",
"members": [
{
"group_id": 1,
"person_id": 1,
"rank": "New"
},
...
]
}
]
I.e., I want to GET/POST/PATCH all fields of the through relation
Try:
class PersonSerializer(serializers.ModelSerializer):
groups = serializers.SerializerMethodField()
def get_groups(self, person):
queryset = GroupPerson.objects.filter(person=person)
return GroupPersonSerializer(queryset, many=True).data
class Meta:
model = Person
fields = ["id", "name", "groups"]
Instead of using
groups = serializers.PrimaryKeyRelatedField(many=True, queryset=Group.objects.all())
Do
groups = GroupSerializer(many=True, read_only=True)
This will allow DRF to serialize groups as a list of nested objects. For more details, check out the documentation for Nested Relationships
i created a model named 'Post'.
here is the code:
class Post(models.Model):
body = models.TextField(max_length=10000)
date = models.DateTimeField(default=datetime.now, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ['-date']
i want to get all objects of Post model with users firstname and lastname.
in views.py:
#api_view(['GET'])
#permission_classes((IsAuthenticated,))
def allPost(request):
allpost = Post.objects.all()
serializer = PostSerializers(allpost, many=True)
return Response(serializer.data)
in serialisers.py:
class UserSerializers(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class PostSerializers(serializers.ModelSerializer):
user = serializers.RelatedField(many=True)
class Meta:
model = Post
fields = ('body','date','user')
You can make a serialzier with firstname and lastname:
class SimpleUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('first_name', 'last_name')
and then use that serializer as subserialiser:
class PostSerializer(serializers.ModelSerializer):
user = SimpleUserSerializer()
class Meta:
model = Post
fields = ('body','date','user')
This generates a JSON blob like:
{
"body": "Sample body text",
"date": "2020-12-11T12:34:56.789Z",
"user": {
"first_name": "MyFirst",
"last_name": "MyLast"
}
}
or you use make use of two CharFields:
class PostSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(source='user.first_name', read_only=True)
last_name = serializers.CharField(source='user.last_name', read_only=True)
class Meta:
model = Post
fields = ('body','date')
this generates as JSON blob:
{
"body": "Sample body text",
"date": "2020-12-11T12:34:56.789Z",
"first_name": "MyFirst",
"last_name": "MyLast"
}
Note: The name of a serializer class is normally singular, so PostSerializer instead of
PostSerializers.
There is no need to use related field in this case. many=True should be used if you're passing multiple objects (like you did with posts).
What you should do is user your UserSerializer in PostSerializer
class PostSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Post
fields = ('body','date','user')
Read docs for more info
https://www.django-rest-framework.org/api-guide/relations/#nested-relationships
I get data like this.
{
"id": 1,
"fields": [
{"id": 1, "name": "att1"},
{"id": 2, "name": "att2"}
]
}
And I need fields without keys like fields: ["att1", "att2"].
I could use SerializerMethod do this. Is there some method like source='form.fields.name'?
CharField(source='form.fields.name') not work with many=True objects.
Code:
class EavForm(models.Model):
name = models.CharField(max_length=300)
class EavAttribute(models.Model):
form = models.ForeignKey(EavForm, on_delete=models.CASCADE, related_name='fields')
name = models.CharField(max_length=300)
class EavAttributeSerializer(serializers.ModelSerializer):
class Meta:
model = EavAttribute
fields = '__all__'
class EavFormSerializer(serializers.ModelSerializer):
fields = EavAttributeSerializer(many=True)
class Meta:
model = EavForm
fields = '__all__'
I have a EavValue object related_to EavForm. How get fields like eav_value_obj.fields as a list?
class EavValue(models.Model):
form = models.ForeignKey(EavForm, on_delete=models.CASCADE, related_name='values')
fields = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='form.fields.name' # not work like this.
)
You can use SlugRelatedField:
class EavFormSerializer(serializers.ModelSerializer):
fields = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='name'
)
class Meta:
model = EavForm
fields = '__all__'