Django使用来自其他模型的信息序列化对象

时间:2019-07-11 12:30:25

标签: python json django serialization django-rest-framework

当前代码

我有两个模型(发布和查看),如下所示。视图是针对哪个用户查看了哪个帖子。

发布模型:

class Post(models.Model):

    creator = models.ForeignKey(User, on_delete = models.CASCADE)
    text = models.CharField(max_length = 255)
    timestamp = models.DateTimeField(default=now)

    def __str__(self):
        return str(self.pk)

查看模型:

class View(models.Model):

    viewer = models.ForeignKey(User, on_delete = models.CASCADE)
    post = models.ForeignKey(Post, on_delete = models.CASCADE)
    timestamp = models.DateTimeField(default=now)

    def __str__(self):
        return str(self.post.pk)

    class Meta:
        unique_together = ('post', 'viewer')

我的views.py当前看起来像这样:

@api_view(['GET'])
@login_required
def get_posts(request):

     posts = list(Post.objects.all())
     data = serialize('json', posts, use_natural_foreign_keys=True)
     return HttpResponse(data, content_type="application/json")

问题

现在,我希望能够序列化许多Post对象,并向每个对象添加一个属性,该属性说明发出请求的用户(request.user)是否查看了Post。

我想收到的结果示例:

[
{
    "model": "posts.post",
    "pk": 1,
    "fields": {
        "creator": ...,
        "content": "This is a sample post",
        "timestamp": "2019-07-07T19:56:07.220Z",
        "viewed_by_user": true <--- I want this attribute
    }
},
{
    "model": "posts.post",
    "pk": 2,
    "fields": {
        "creator": ...,
        "content": "This is another sample post",
        "timestamp": "2019-07-10T13:04:19.220Z",
        "viewed_by_user": false <--- I want this attribute
    }
}
]

我可以使用Django序列化程序实现此目标吗?我应该以其他方式构造模型吗?

我正在使用django-rest-framework来处理请求。您可以问我是否需要其他信息来回答我的问题。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以使用DRF中的标准ModelSerializer

  

serializers.py

from rest_framework import serializers

from .models import Post


class PostSerializer(serializers.ModelSerializer):
    viewed_by_user = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = ('pk', 'creator', 'text', 'timestamp', 'viewed_by_user')

    def get_viewed_by_user(self, instance):
        user = self.context['request']. user
        return instance.view_set.filter(viewer=user).exists()

然后

  

views.py

from rest_framework.response import Response
...

from .serializers import PostSerializer


@api_view(['GET'])
@login_required
def get_posts(request):
     posts = Post.objects.all()
     serializer = PostSerializer(posts, many=True, context={'request': request})
     return Response(serializer.data)

在您看来,可以通过将当前的PostSerializer对象提供给序列化程序的上下文,来使用新创建的request

此后,您可以受益于SerializerMethodField来显示viewed_by_user属性。

如果还有其他问题,请确保在下面发表评论。 :)

答案 1 :(得分:1)

您可以使用DRF来实现此目的,并且不需要单独的模型来统计查看过特定帖子的用户

models.py

class Post(models.Model):

    creator = models.ForeignKey(User, on_delete = models.CASCADE)
    text = models.CharField(max_length = 255)
    timestamp = models.DateTimeField(default=now)
    viewed_by = models.ManyToManyField(User, null=True, blank=True, related_name='viewer')

    def __str__(self):
        return str(self.pk)

serializers.py

使用serializerMethord检查用户是否查看了特定帖子

from rest_framework import serializers
from .models import Post


    class PostSerializers(serializers.ModelSerializer):

        viewed = serializers.SerializerMethodField()

        class Meta:
            model = Post
            fields = [
                'viewed',
                'text',
                'timestamp'

            ]

        def get_viewed(self, obj):
            print(self.context['request'].user, obj.viewed_by)
            if self.context['request'].user in obj.viewed_by.all():
                return True
            return False

然后在views.py

from rest_framework.generics import ListAPIView

from .models import Post
from .serializers import PostSerializers

    class PostListView(ListAPIView):
        queryset = Post.objects.all()
        serializer_class = PostSerializers

您可以通过

计算每个观看次数
class PostDetailView(RetrieveAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializers

    def get(self, request, *args, **kwargs):
        data = self.get_object()
        data.viewed_by.add(request.user)
        data.save()

        return self.retrieve(request, *args, **kwargs)