Джанго сериализует объект с информацией из другой модели - PullRequest
0 голосов
/ 11 июля 2019

Текущий код

У меня есть две модели (Post и View), как показано ниже.Представление - это то, для чего пользователь видел какое сообщение.

Модель сообщения:

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) просмотрел сообщение.

Пример результата, который я хотел бы получить:

[
{
    "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 ]

1 голос
/ 11 июля 2019

Этого можно добиться с помощью 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)
1 голос
/ 11 июля 2019

Вы можете использовать стандарт ModelSerializer от DRF:

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.

Если у вас есть какие-либо дополнительные вопросы, обязательно оставьте комментарий ниже.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...