Метод вычисления сохраненных сообщений Python Django

#python #django #api #serialization #model

#python #django #API #сериализация #Модель

Вопрос:

Предполагая, что я использую модель django по умолчанию, модель Post (код ниже) и модель SavedPost, которая связывает пользователя с сообщением (если определенный пользователь с определенным сообщением существует, то это сообщение сохраняется для этого пользователя) и модель подписчика, которая связывает 2 пользователя (аналогично SavedPost).

Что я пытаюсь сделать: API, который для пользователя, они получают все сообщения для пользователей, на которых они подписаны, кроме того, у каждого из этих сообщений есть дополнительное «поле», чтобы указать, сохранено ли это сообщение или нет.

 class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post_type = models.CharField(max_length=1, choices=[('B', 'Blog'), ('V', 'Video')], default='B')
    file_path = models.URLField(null=True)
    title = models.CharField(max_length=255)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class SavedPost(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        # A user can save a post only once.
        unique_together = ('user', 'post')

class Follower(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user")
    follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name="follower")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        # A user can follow another user only once
        unique_together = ('user', 'follower')
  

Сериализатор сообщений:

 class PostSerializer(serializers.ModelSerializer):
    """
    Nested serializer for post using SimpleUser and Kingdom.
    """

    class Meta:
        model = Post
        fields = ('id', 'user', 'post_type', 'file_path',
                  'title', 'description', 'created_at', 'updated_at')

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['user'] = UserSerializer(
            User.objects.get(pk=data['user'])).data
        return data
  

Просмотр API:

 @permission_classes([IsAuthenticated,])
@api_view(['GET'])
def get_following(request):
    user = request.user
    following = Follower.objects.filter(follower=user).values('user')
    # saved_posts = SavedPost.objects.filter(user=user, post__user__in=following).order_by('-post__created_at')
    posts = Post.objects.filter(user__in=following).order_by('-created_at')

    serializer = PostSerializer(posts, many=True, context={'request': request})
    return JsonResponse(serializer.data, safe=False)
  

Пока что с помощью сделанного мной представления я могу получить все сообщения, за которыми следует request.user, но в нем не указано, сохранены они или нет. Я ищу логическое значение ‘is_saved’ в сообщении, чтобы указать, сохранено ли это сообщение для этого пользователя или нет.

Любая помощь / метод для этого приветствуется. Спасибо.

Комментарии:

1. можете ли вы добавить PostSerializer сериализатор?

2. Добавлен постсериализатор!

Ответ №1:

Использовать serializers.SerializerMethodField как

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

    def get_is_saved(self, post_instance):
        return SavedPost.objects.filter(user=post_instance.user, post=post_instance).exists()

    class Meta:
        model = Post
        fields = ['id', 'user', 'post_type', 'file_path',
                  'title', 'description', 'created_at', 'updated_at', 'is_saved']

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['user'] = UserSerializer(
            User.objects.get(pk=data['user'])).data
        return data  

Комментарии:

1. Это сработало, в поля следует добавить одно отсутствующее ‘is_saved’. Спасибо

Ответ №2:

Прежде всего, просто для ясности, я буду определять related_name вариант для ForeignKey s в SavedPost — вам решать, реализовывать это или нет:

 class SavedPost(models.Model):
    user = models.ForeignKey(User, related_name="saved", on_delete=models.CASCADE)
    post = models.ForeignKey(Post, related_name="saved", on_delete=models.CASCADE)
    ...
  

Теперь, в вашем PostSerializer , вы могли бы добавить это поле (не забудьте добавить его в fields переменную во Meta внутреннем классе — это если вы используете ModelSerializer ):

 class PostSerializer(serializers.ModelSerializer):
    saved = SavedPostSerializer(many=True)
    ...
  

Чтобы закончить это, определите свой SavedPostSerializer — выше PostSerializer , если в том же файле / модуле:

 class SavedPostSerializer(serializers.ModelSerializer):
    class Meta:
        model = SavedPost
        fields = "__all__"
  

При этом ваш json должен иметь вложенное поле с saved ключом, содержащим массив SavedPost s, если таковые имеются, связанные с полученными Post s.

Комментарии:

1. Я понимаю, что вы имеете в виду. Есть ли способ сделать атрибут ‘saved’ из PostSerializer логическим? Должно быть истинным, если есть сохраненный пост, и ложным, если нет.

2. В этом случае, возможно, вы могли бы переопределить to_representation в PostSerializer и присвоить его значение на основе того, есть ли какие-либо элементы в saved списке; например bool(data["saved"]) .