简体   繁体   中英

Django Serialize return id of user, but i need username

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

Try this using DRF

serializer.py :

class HighScoreSerializer(serializers.ModelSerializer):
        user = serializers.SlugRelatedField(
            slug_field='username'
        )

    class Meta:
        model = HighScore
        fields = '__all__'

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__'

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM