How to include in queryset details fields of a for

2019-03-02 17:20发布

问题:

I use rest_api in django in order to display a queryset of "chats". I tried to get it done for a while, without success...

in angularjs controller I call a function which do the following:

$scope.conversations =   $http.get('/api/chats/').then(function(response){
    return response.data;
});

in urls.py of the rest_api app I put this:

url(r'^chats/$', login_required(views.chatsViewSet.as_view()) ),

in view.py of the rest_api I put this:

from rest_framework.generics import ListCreateAPIView
from serializers import ChatsSerializer

class ChatsViewSet(ListCreateAPIView):
    serializer_class = ChatsSerializer
    def get_queryset(self):
        return Message.objects._folder(('sender', 'recipient'), {},order_by='-sent_at')

and in serializers.py in the rest_api I put this:

from postman.models import Message
from rest_framework import serializers

class ChatsSerializer(serializers.ModelSerializer):
  class Meta:
    model = Message
    fields = ('id', 'sender', 'recipient','thread','subject','moderation_reason','body')
    ordering =['-thread']

The 'sender' and the 'recipient' fields in the Message of postman model are foreign keys.

Here is the definition of sender, for instance, in the Message Model in postman:

sender = models.ForeignKey(get_user_model(), related_name='sent_messages', null=True, blank=True, verbose_name=_("sender"))

I would like that the queryset in rest_api include not only the ID of the sender but also its username field...

I tried to read some posts like using 'extra' in rest_api but I didn't figure it out. I will be grateful if somebody could write me explicit instruction how to do it...

回答1:

You can make a property on your model:

class Message(models.Model):
    # some code...

    @property
    def sender_name(self):
        return self.sender.name # username or whatever

Then is you serializer you create a custom field:

class ChatsSerializer(serializers.ModelSerializer):
    # some code...

    sender_name = serializers.Field(source = 'sender_name') # source = 'name of property or method' you dont have to pass it in this example becouse model property has the same name as this serializer attribute

    class Meta:
         fields = ('sender_name', 'id', 'sender', 'recipient','thread','subject','moderation_reason','body')

Now you have an 'sender_name' object in your JSON response.

That's just one method I hope it helps :)

The second one is to add an UserModelSerializer:

class UserModelSerializer(serializers.ModelSerializer):

    class Meta:
         model = get_user_model()

class ChatsSerializer(serializers.ModelSerializer):
    # some code...

    sender = UserModelSerializer()
    recipient = UserModelSerializer()

    class Meta:
         fields = ('sender_name', 'id', 'sender', 'recipient','thread','subject','moderation_reason','body')

Retriving is ok. But creating and updating with it is a hard piece of coding.

You can always create an Angular service for your 'sender' object and after reciving your chat messages with only foreign keys, request data from a 'UserModelView' with those 'FK' and bind them together. That's a third method.