#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"])
.