Reputation: 15
this is my model:
class HighScore(models.Model):
user = models.OneToOneField(UserManagement, on_delete=models.CASCADE)
highScore = models.IntegerField(blank=True, null=True)
createDate = models.DateTimeField()
def __str__(self):
return "{}_HighScore".format(self.user)
and this is my view:
def pullUserNames(request):
top_score = createHighScore()
top_users = (HighScore.objects.order_by('-highScore').filter(highScore__in=top_score[:10]))
top_users_serialized = serializers.serialize('json', top_users)
top_users_json = json.loads(top_users_serialized)
data = json.dumps(top_users_json)
return HttpResponse(data)
response is:
[{"model": "scoremg.highscore", "pk": 2, "fields": {"user": 2, "highScore": 650, "createDate": "2018-12-25T20:34:51.826Z"}}, {"model": "scoremg.highscore", "pk": 1, "fields": {"user": 1, "highScore": 271, "createDate": "2018-12-17T21:48:34.406Z"}}]
in this response {"user": 2, "highScore": 650, "createDate": "2018-12-25T20:34:51.826Z"}
, highScore and createDate have good face, but user is id not username, how can i edit it to return username?
I test print(top_users) after line two in above view, and it print --> user2_HighScore
user1_HighScore
thanks
Upvotes: 1
Views: 1349
Reputation: 11
In the serializers file , add this code to get the username instead of user id. Here , you are overriding the user field of model serializer to get the username name instead of user id.
class SearchHistorySerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(
read_only=True,
slug_field='username'
)
class Meta:
model = SearchHistory
fields = '__all__'
Upvotes: 1
Reputation: 17
In the serializer class of the serializer.py file, add the following line of code:
user = serializers.SlugRelatedField(
read_only=True,
slug_field='username'
)
This will tell your serializer to fetch and return username field from the User table.
Upvotes: 0
Reputation: 9257
I think, with the combination of QuerySet's Annotation
and a custom function that serialize your data you can solve your issue.
Here is an example how you can do it:
import json
from django.db.models import F
def custom_serializer(a):
"""
Handy creation of the Queryset fields
And we exclude the fields that starts by '__'
which are Django internal references
This will lead to the representation of the annotated fields
that are generated by the QuerySert annotation
which are ignored by serializers.serialize() function
"""
return [{
'model': a.model.__name__, 'pk': k.pk, 'fields': {
i: j for i, j in k.__dict__.items() if not i.startswith('_')
}
} for k in a]
# Here we annotate a new field called username
# which holds the user's username using the F expression
top_users = HighScore.objects.order_by('highScore').filter(
highScore__in=top_score[:10]
).annotate(username=F('user__username'))
top_users_serialized = custom_serializer(top_users)
print(json.dumps(top_users_serialized))
You'll get something like this:
[{
"model": "scoremg.highscore",
"pk": 2,
"fields": {
"id": 2, # pk
"user_id": 2 # your user id
"username": "test", # your user's username
"highScore": 650,
"createDate": "2018-12-25T20:34:51.826Z"
}
},
...
]
Edit:
A better approach without using a custom function, you can use queryset.values()
method like this example:
top_users = HighScore.objects.order_by('highScore').filter(
highScore__in=top_score[:10]
).annotate(username=F('user__username'))
top_users_serialized = [elm for elm in top.users.values()]
print(json.dumps(top_users_serialized))
You'll get something like this:
[{
"id": 2, # pk
"user_id": 2 # your user id
"username": "test", # your user's username
"highScore": 650,
"createDate": "2018-12-25T20:34:51.826Z"
},
...
]
For more informations, please refer to: F() expression, QuerySet Annotation and QuerySet values
Upvotes: 0
Reputation: 1847
Try this using DRF
serializer.py
:
class HighScoreSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(
slug_field='username'
)
class Meta:
model = HighScore
fields = '__all__'
Upvotes: 2