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_details
是read_only=True
我将在GET
请求中获取作者的所有数据,并且可以通过author=request.user.id
创建新提案。
一瞬间:
我没有在author
字段上使用blank=True
,因为我必须确保该字段不为空。所以我的观点看起来和我上面写的一样(post
ProposalsList
)。
再次感谢@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 错误