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"
}
Related
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
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 am want to serialize the list during update, example making patch call to update below user profile with "cuisine"
Get call
**http://localhost:8000/api/v1/chef/rayees/details**
{
"user": {
"pk": 2,
"username": "rayees",
"email": "rayees.xxxx#yahoo.co.in",
"first_name": "Rayees",
"last_name": "xxxx",
"user_type": "Chef"
},
"first_name": "Rayees",
"last_name": "xxx",
"bio": "TEST BIO",
"chef_cost": "10.00",
"serve_type": "Non-Veg",
"cuisine": [
"South Indian",
"North Indian"
]
}
Here is my serializer class, i think "serializers.SerializerMethodField()" is read only one and "cuisine" not getting updated during patch operation , If want to serialize both get and patch, what should i do here
class ChefProfileDetails(serializers.ModelSerializer):
chef_date = AvailabilityDetails(many=True, read_only=True)
first_name = serializers.CharField(source='user.first_name', read_only=True)
last_name = serializers.CharField(source='user.last_name', read_only=True)
cities = CitySerializer(many=True, read_only=True)
cuisine = serializers.SerializerMethodField()
user = UserDetailsSerializer(read_only=True)
class Meta:
model = Chef
fields = ('user', 'first_name', 'last_name',
'bio', 'chef_cost', 'serve_type', 'cuisine', 'chef_date', 'cities')
def get_cuisine(self, obj):
cuisine_list = []
for i in obj.cuisine.all():
cuisine_list.append(i.cuisine)
return cuisine_list
There is one-to-many connection between Chef and Cuisine models, so try to use RelatedField:
class ChefProfileDetails(serializers.ModelSerializer):
cuisines = serializers.RelatedField(many=True)
class Meta:
model = Chef
fields = ('user', 'first_name', 'last_name',
'bio', 'chef_cost', 'serve_type',
'cuisine', 'chef_date', 'cities')
I think that should work.
You can achieve what you need by defining a Custom Field and then provide your definition of getter and setter in to_representation() and to_internal_value() respectively.
Code:
class CuisineField(serializers.Field):
def to_representation(self, value):
cuisine_list = []
for i in value:
cuisine_list.append(i.cuisine)
return cuisine_list
def to_internal_value(self, data):
""
Do whatever you want to do in patch
""
And then define cuisine as CuisineField in your serializer as
cuisine = CuisineField()
Refer DRF docs for custom fields
So I have a model called 'Task' and the task has 'UserProfile's working on them. These 'UserProfile' models are just normal Users but inside the App of the 'Task'.
This is the API I have right now:
"tasks": [
{
"id": 1,
"name": "Läs På Internet",
"description": "asdasdasdasa",
"created": "2019-06-08",
"deadline": "2019-06-19",
"state": "new",
"stickers": [
{
"id": 1,
"name": "Detta är en sticker",
"content": "Sillicon Valley",
"created": "2019-06-08",
"creator": {
"id": 1,
"user": 1
}
}
],
"checkmarks": [
{
"id": 1,
"name": "Googla",
"checked": false
}
],
"workers": [
{
"id": 1,
"user": 1
}
]
},
{
"id": 2,
"name": "Läs i böcker",
"description": "aaa",
"created": "2019-06-10",
"deadline": "2019-06-25",
"state": "done",
"stickers": [],
"checkmarks": [],
"workers": [
{
"id": 1,
"user": 1
}
]
}
],
As you can see every user now just has 'id' and 'user', which are both the ID. How do I get the username for every user and display them in the rest api?
# Users
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = 'All Users'
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_data(sender, update_fields, created, instance, **kwargs):
if created:
user = instance
profile = UserProfile.objects.create(user=user)
#Tasks
class Task(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=2000)
created = models.DateField(default=date.today)
deadline = models.DateField(default=date.today)
state = models.CharField(max_length=20, default='new')
stickers = models.ManyToManyField(Sticker, blank=True)
checkmarks = models.ManyToManyField(Checkmark, blank=True)
workers = models.ManyToManyField(UserProfile, blank=True, related_name='TaskWorkers')
class Meta:
verbose_name_plural = 'Tasks'
def __str__(self):
return "{name}".format(name=self.name)
serializers:
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('id', 'user')
class TaskSerializer(serializers.ModelSerializer):
stickers = StickerSerializer(many=True, read_only=True)
checkmarks = CheckmarkSerializer(many=True, read_only=True)
workers = UserProfileSerializer(many=True, read_only=True)
class Meta:
model = Task
fields = ('id', 'name', 'description', 'created', 'deadline', 'state', 'stickers', 'checkmarks', 'workers')
views:
class TaskView(viewsets.ModelViewSet):
http_method_names = ['get', 'post', 'put', 'delete', 'patch']
queryset = Task.objects.all()
serializer_class = TaskSerializer
class UserTaskView(TaskView):
def get_queryset(self):
return Task.objects.filter(workers__user=self.request.user)
The User Views are for displaying only for the users that are assigned!
You can either update the user serializer inside your UserProfileSerializer with something like this (creating a serializer with the fields you want for the User):
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = ('id', 'user')
or this (accessing user fields from within the UserProfileSerializer):
class UserProfileSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
class Meta:
model = UserProfile
fields = ('id', 'user', 'username')
As documented below in
https://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations
You can get the user profile details inside the tasks as:
class TaskSerializer(serializers.ModelSerializer):
......
user = UserSerializer()
class Meta:
model = Task
fields = (...., 'user',....., 'workers')
This will return all the fields in the the user model as part of the task nested json
I'm new to Django I want to get profile image from another model topic
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
file = models.ImageField(upload_to='profile_image', blank=True)
def __unicode__(self):
return u'%s' % self.user
class Topics(models.Model):
user = models.ForeignKey(User)
title = models.charField(max_length = 55)
serializers.py
User = get_user_model()
class pic(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['file']
class UserInfo(serializers.ModelSerializer):
username = pic(read_only=True)
class Meta:
model = User
fields = ['username','first_name',]
class TopicSerializer(serializers.ModelSerializer):
user= UserInfo(read_only=True)
class Meta:
model=Topics
fields = ('user','title',)
I'm getting like this:
"user": {
"username": {},
"first_name": ""
},
"title": "Django the title",
Now I need every file field related to Topics field with the first name and email of the user.
I want to like this:
"user": {
"username": "akash",
"first_name": "Akash DK"
"file":"static/imag.png"
},
"title": "Django the title",
Thanks in advance
You could use a SerializerMethodField in your UserInfo serializer to lookup the profile image and add it to the output data.
class UserInfo(serializers.ModelSerializer):
file = serializers.SerializerMethodField()
def get_file(self, user):
return UserProfile.objects.get(user=user).file.url
class Meta:
model = User
fields = ['username','first_name', 'file']