1

У меня есть модель под названием UserProfile, которая является OneToOneField по умолчанию User. У меня есть модель Post, которая имеет User как ManyToManyField. Я не могу написать сериализатор для Post, который включает в себя ответы User.Как сериализовать в Django Rest Framework с большим числом полей

Моя UserProfile модель:

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    name = models.CharField(max_length=255, null=True) 
    profile_picture = models.CharField(max_length=1000, null=True) 

Моя Post модель:

class Post(models.Model): 
    text = models.TextField(null=True) 
    title = models.CharField(max_length=255, null=True) 
    created_at = models.DateTimeField(auto_now_add=True) 
    updated_at = models.DateTimeField(auto_now=True) 

    user = models.ManyToManyField(User) 

Мой Post сериализатору:

class PostSerializer(serializers.ModelSerializer): 
    users = UserProfileSerializer(source='user.userprofile', many=True) 

    class Meta: 
     model = Post 
     fields = ('id', 'text', 'title', 'users') 

С выше сериализатором я получаю следующее сообщение об ошибке:

Got AttributeError when attempting to get a value for field `users` on serializer `WorkSerializer`. 
The serializer field might be named incorrectly and not match any attribute or key on the `Work` instance. 
Original exception text was: 'ManyRelatedManager' object has no attribute 'userprofile'. 

EDIT: Я создал еще один сериалайзер UserSerializerForPost, который используется в PostSerializer:

class UserSerializerForPost(serializers.ModelSerializer): 
    user = UserProfileSerializer(source='userprofile') 

    class Meta: 
     model = User 
     fields = ('user',) 


class PostSerializer(serializers.ModelSerializer): 
    users = UserSerializerForPost(source='user', many=True) 

    class Meta: 
     model = Post 
     fields = ('id', 'text', 'title', 'users') 

Хотя это работает, но я получаю UserProfile ответ в словаре user как users списка:

"users": [ 
    { 
    "user": { 
     "id": 2, 
     ... 
    }, 
    { 
    "user": { 
     "id": 4, 
     ... 
    } 
    } 
] 

Но я хочу:

"users": [ 
    { 
    "id": 2, 
    ... 
    }, 
    { 
    "id": 4, 
    ... 
    } 
    } 
], 
+0

Это потому, что вы определяете поле 'user' в сериализаторе UserSerializerForPost. Удалите это поле. – Gocht

+0

без определения его, как я могу предоставить 'source'? – avi

+0

Вам просто нужно определить модель в вашем мета-классе. – Gocht

ответ

2

После решения работал для меня, и она даже не требует создания UserSerializerForPost:

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

    class Meta: 
     model = Post 
     fields = ('id', 'text', 'title', 'users') 

    def get_users(self, obj): 
     response = [] 
     for _user in obj.user.all(): 
      user_profile = UserProfileSerializer(
       _user.userprofile, 
       context={'request': self.context['request']}) 
      response.append(user_profile.data) 
     return response 

EDIT: Хорошо, я нашел еще лучший подход, чем выше. Сначала добавьте get_user_profiles к Post:

class Post(models.Model): 
    text = models.TextField(null=True) 
    title = models.CharField(max_length=255, null=True) 
    created_at = models.DateTimeField(auto_now_add=True) 
    updated_at = models.DateTimeField(auto_now=True) 

    user = models.ManyToManyField(User) 

    def get_user_profiles(self): 
     return UserProfile.objects.filter(user__post=self) 

Тогда я обновил свой PostSerializer с:

class PostSerializer(serializers.ModelSerializer): 
    users = UserProfileSerializer(source='get_user_profiles', many=True) 

    class Meta: 
     model = Post 
     fields = ('id', 'text', 'title', 'users') 

Это слишком уборщик версия, что раньше.

Смежные вопросы