Django Rest Framework嵌套对象使用request.user创建

时间:2017-07-23 14:20:17

标签: django model django-rest-framework authorization

我希望我的访问者能够创建并获取提案列表。

用户发送除Proposal作者之外的所有数据(因为auth是用户自己),所以我尝试使用request.user扩展request.data,如下所示:

# proposals/views.py
class ProposalsList(ListCreateAPIView):
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset = Proposal.objects.all()
    serializer_class = ProposalSerializer

    def post(self, request, *args, **kwargs):
         serializer = self.get_serializer(data={
            **request.data,
            "author": request.user.id,
          })
          serializer.is_valid(raise_exception=True)
          self.perform_create(serializer)
          headers = self.get_success_headers(serializer.data)
          return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

虽然,我想用序列化作者(用户)获取提案列表,所以我的序列化器看起来像:

# proposals/serializers.py
class ProposalSerializer(serializers.ModelSerializer):
    author = UserSerializer()
    class Meta:
         model = SeekerProposal
         fields = ('text', 'author')

问题是我正确获取用户列表(序列化为dict),但我无法发布(创建新)提案,因为它想要"作者&#34 ;是一个字典(这是因为我使用嵌套的序列化器作者= UserSerializer())。

问题:

  1. 有没有办法让视图成为ListCreateAPIView和author = UserSerializer(),同时获取包含序列化数据的列表并通过request.user.id创建提案?
  2. 也许还有另一种方法可以将授权用户添加到Proposal作者字段中?
  3. 另外,这是我的模特:

    # proposals/models.py
    class Proposal(models.Model):
        text = models.TextField(blank=False, null=False)
        author = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.SET(get_sentinel_user),
        )
    

    答案

    用户@zaidfazil帮助我解决了问题。 我需要在序列化程序中再添加一个额外的字段,以便显示序列化的作者详细信息:

    # proposals/serializers.py
    class ProposalSerializer(serializers.ModelSerializer):
        author_details = UserSerializer(source='author', read_only=True)
        class Meta:
            model = SeekerProposal
            # author will be user id, and author_details will be serialized dict
            fields = ('text', 'author', 'author_details')
    

    由于author仍然只是用户ID而author_detailsread_only=True,我会在GET请求中获取作者的所有数据,并可以{{1}创建新提案}}

    片刻:

    我在author=request.user.id字段上没有使用blank=True,因为我必须确保此字段不为空。所以我的观点与我在上面写的一样(author上的post)。

    再次,非常感谢@zaidfazil!如果我写错了,请写信给我,我在stackoverflow上有点不高兴。

1 个答案:

答案 0 :(得分:0)

通常的方式是在模型中将author字段定义为blank=True,并在保存序列化程序时传递用户,

author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user), blank=True)

serializers.py,

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('email', 'first_name', .....)

class ProposalSerializer(serializers.ModelSerializer):
    author_details = UserSerializer(source='author', read_only=True)
    class Meta:
        model = SeekerProposal
        fields = ('text', 'author', 'author_details')

然后,在您看来,

class ProposalsList(ListCreateAPIView):
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset = SeekerProposal.objects.all()
    serializer_class = SeekerProposalSerializer

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)