Сериализация вложенных объектов внешнего ключа

#python #django #serialization #django-rest-framework

#python #django #сериализация #django-rest-framework

Вопрос:

кто бы ни читал это, надеюсь, у вас все хорошо. Я создаю приложение для социальных сетей, которое включает в себя пост, лайки и комментарии, как и любой другой сайт в социальных сетях, я пытаюсь отправить данные из своего бэкэнда во внешний интерфейс через сериализаторы, проблема, с которой я сталкиваюсь, заключается в том, что я не могу получить вывод целых данных, но частичныйданные. Следующее представляет мой models.py для объектов, которые я пытаюсь сериализовать

models.py

 class User(AbstractUser):
    contact_no = models.CharField(max_length=15,null=True,blank=True)
    profile_picture=models.ImageField(upload_to=to_upload,default="defaultprofile.jpg")

class Post(models.Model):
    posted_by=models.ForeignKey(User,on_delete=models.CASCADE)
    date= models.DateField(auto_now=True)
    time=models.TimeField(auto_now=True)
    content=models.CharField(max_length=2000)
    media=models.ImageField(default=None,blank=True,upload_to=to_upload_post)

class Like(models.Model):
    Liked_by=models.ForeignKey(User,on_delete=models.CASCADE,related_name="likes")
    post=models.ForeignKey(Post,on_delete=models.CASCADE)
    date = models.DateField(auto_now=True)
    time = models.TimeField(auto_now=True)
  

и сериализаторы, которые я использую, это

serializers.py

 class UserSerializer(serializers.ModelSerializer):
   
    class Meta:
        model=User
        fields=['id','username','first_name','last_name','profile_picture']

class LikeSerializer(serializers.ModelSerializer):
    Liked_by=UserSerializer()
    class Meta:
        model=Like
        fields=['Liked_by']

class PostSerializer(serializers.ModelSerializer):
    posted_by=UserSerializer()
    likes=LikeSerializer(many=True)

    class Meta:
        model=Post
        fields=['posted_by','id','content','date','time','media','likes']
  

Это не вызывает никаких ошибок при импорте, но не дает полных данных.

Результат, который я получаю, это

  {
   'posted_by': 
              OrderedDict([
                           ('id', 7), 
                           ('username', 'user'), 
                           ('first_name', ''), 
                           ('last_name', ''), 
                           ('profile_picture', '/media/defaultprofile.jpg')]), 
  'id': 4, 
  'content': 'This is a test post for likes', 
  'date': '2020-10-22', 
  'time': '05:34:55.979863', 
  'media': None
}
  

но то, что я пытаюсь получить, это

Желаемый результат

 {
   'posted_by': 
              OrderedDict([
                           ('id', 7), 
                           ('username', 'user'), 
                           ('first_name', ''), 
                           ('last_name', ''), 
                           ('profile_picture', '/media/defaultprofile.jpg')]), 
  'id': 4, 
  'content': 'This is a test post for likes', 
  'date': '2020-10-22', 
  'time': '05:34:55.979863', 
  'media': None
  'likes':
          ['Liked_by':
                     OrderedDict([
                           ('id', 1), 
                           ('username', 'user1'), 
                           ('first_name', ''), 
                           ('last_name', ''), 
                           ('profile_picture', '/media/defaultprofile.jpg')
]
)
  
}
  

Любые рекомендации или рекомендации по стратегии будут высоко оценены.

Ответ №1:

Попробуйте установить related_name так же, как вы сделали для поля Liked_by:

 post=models.ForeignKey(Post,on_delete=models.CASCADE, related_name='likes')
  

К сожалению, некоторые исключения маскируются фреймворком django rest, поскольку он пытается перехватить некоторые из них, в том числе AttributeError для выполнения проверок существования полей.

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

1. Спасибо, это сработало, но как я могу ссылаться на сообщение как на лайки? поскольку лайки — это просто связь сообщений?

2. Кажется, что связанное имя здесь сбивает с толку. Пожалуйста, обратите внимание, что, указывая связанное имя, вы сообщаете Django, как вызывать отношение с другой стороны. Вы говорите Django поместить поле в любой объект post с именем likes для ссылки на связанные лайки. Я также поместил ссылку на документацию.

Ответ №2:

Несколько вещей, на которые следует обратить внимание:

  1. сериализаторы работают с данными, а не с классами сериализаторов. Вместо этого вам нужно создать SerializerMethodField() и создать для него средство получения.
  2. Чтобы избежать проблемы со спамом базы данных с запросами, не забудьте добавить .select_related() / .prefetch_related() в ваш набор запросов.
  3. Считается хорошей практикой использовать имена полей в нижнем регистре 🙂

пример:

 class LikeSerializer(serializers.ModelSerializer):
    Liked_by = serializers.SerializerMethodField()
    class Meta:
        model=Like
        fields=['Liked_by']
    
    def get_Liked_by(self, instance):
        return UserSerializer(instance.Liked_by, many=False).data