如何使用多对多字段

时间:2015-10-20 13:51:45

标签: python django python-2.7 serialization django-rest-framework

我有一个名为UserProfile的模型,它是默认OneToOneField模型的User。我有一个Post模型,UserManyToManyField。我无法为Post编写序列化程序,其中包含User个回复。

我的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'.

编辑:我创建了另一个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,
    ...
    }
  }
],

1 个答案:

答案 0 :(得分:3)

以下解决方案为我工作,甚至不需要创建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

编辑:好的,我找到了比上面更好的方法。首先将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')

这比之前的版本更清晰。