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

Posted

技术标签:

【中文标题】Django Rest Framework 嵌套对象使用 request.user 创建【英文标题】:Django Rest Framework nested objects create with request.user 【发布时间】:2017-12-29 04:25:13 【问题描述】:

我希望我的访问者具有创建和获取提案列表的功能。

用户发送除了提案作者之外的所有数据(因为身份验证是用户自己),所以我试图用 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')

问题是我正确获取用户列表(序列化为字典),但我无法发布(创建新)提案,因为它想“作者”成为字典(它发生了因为我使用的是嵌套序列化器 author = UserSerializer())。

问题:

    有没有办法让 view 成为 ListCreateAPIView 和 author = UserSerializer() 而 GET 包含序列化数据的列表并通过 request.user.id 创建提案? 也许还有其他方法可以将授权用户添加到提案作者字段?

另外,这是我的模型:

# 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 请求中获取作者的所有数据,并且可以通过author=request.user.id 创建新提案。

一瞬间:

我没有在author 字段上使用blank=True,因为我必须确保该字段不为空。所以我的观点看起来和我上面写的一样(postProposalsList)。

再次感谢@zaidfazil!如果我写错了请写信给我,我在 *** 上有点菜鸟。

【问题讨论】:

某种答案是创建名为 ProposalNestedSerializer 的新序列化程序,它继承我的 ProposalSerializer 并扩展 author = UserSerializer(),同时将其从 ProposalSerializer 中删除。所以现在,我将 ProposalNestedSerializer 用于 GET(并获取序列化作者作为响应)并将 ProposalSerializer 与 POST 一起使用(并且可以仅使用 request.user.id 创建提案) 【参考方案1】:

通常的方法是在模型中将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)

【讨论】:

谢谢!但是仍然存在问题:首先,在 GET 上,我需要一个带有序列化作者的提案列表,在 POST 上创建带有 author=request.user.id 的提案(但我不能,因为如果我在 ProposalSerializer 中使用 author = UserSerializer() 它在创建时询问对象)其次,我不想让作者空白=True,因为这有点危险(我需要在很多情况下进行身份验证) 制作作者blank=True不会产生任何影响,因为分配用户只会在幕后处理。否则,它本身就会失去安全性,user 字段仍然是强制性的。关于作者详细信息的问题,您可以在 GET 请求中添加 read_only 字段,以查看现有作者信息的详细信息。我会尽快更新我的答案。 你给了我解决这个问题的方法!我会在我的问题中描述它。但是有两件事:我需要确保作者不是空白的,所以我真的不想用户 blank=True 而我没有,你也可以在你的答案中添加'author_details'到你的答案中,让其他人成为不要混淆他们为什么会出错)

以上是关于Django Rest Framework 嵌套对象使用 request.user 创建的主要内容,如果未能解决你的问题,请参考以下文章

django-rest-framework、多表模型继承、ModelSerializers 和嵌套序列化器

python django-rest-framework 3.3.3 更新嵌套序列化程序

使用 Django Rest Framework 3.2.2 具有现有对象的可写嵌套序列化程序

需要 Django Rest Framework 嵌套序列化程序 = False 错误

Django REST Framework:嵌套序列化程序未出现

在 Django REST Framework 中显示嵌套实体