Django Rest Framework:从序列化器中的视图访问传递的参数
Django Rest Framework: Access to passed arguments from views in serializers
在问这个问题之前,我看到了以下链接,但它们对我没有任何帮助:
pass extra arguments to serializer
我有一个作者模型,它有默认 Django 用户模型的外键:
apps/author/models.py
class Author(models.Model):
user = models.OneToOneField(
User,
related_name='author',
on_delete=models.CASCADE,
default="",
)
is_author = models.BooleanField(
default=True,
)
full_name = models.CharField(
max_length=100,
default="",
)
def __str__(self):
return self.user.username
Post 模型有指向 Author 的外键。
apps/posts/models.py
class Post(models.Model):
author = models.ForeignKey(
Author,
related_name="posts",
on_delete=models.CASCADE,
)
title = models.TextField(
null=True,
blank=True,
)
content = models.TextField(
null=True,
blank=True,
)
is_draft = models.BooleanField(
default=True
)
created_at = models.DateTimeField(
auto_now_add=True,
null=True,
)
published_at = models.DateField(
null=True,
blank=True,
default=None,
)
def __str__(self):
return str(self.id) + ", " + self.title
问题定义: 为了创建一个新的 post,我在视图中从 self.request.user
获取当前用户,并将其传递给Post序列化器。但是每当我想使用以下对 localhost:8000/posts/
的请求创建一个新的 post 时,我都会遇到错误:
# I also added JWT authorization header to the postman! and it doesn't have any problem at this level
{
"title": "",
"content": ""
}
错误
这是我在 apps/posts/views.py
中所做的:
def get_serializer_context(self):
context = super().get_serializer_context()
context["user"] = self.request.user
context["author"] = Author.objects.get(user=context["user"])
print(context["author"])
return context
print(context["author"])
运行良好并打印出当前作者。问题是我无法在序列化程序中获取它。
class PostSerializer(serializers.ModelSerializer):
# author = serializers.SerializerMethodField('get_author')
#
# def get_author(self, obj):
# print('current author', self.context["author"])
# return self.context["author"]
class Meta:
model = Post
fields = '__all__'
extra_fields = ['author']
#def create(self, validated_data):
#print(self.context["author"])
#print(self.context)
PS: 评论是我试过的方法,还是报错。我该如何解决这个问题?
也许你应该在 PostSerializer 的作者字段中添加“required=False”,这将避免“此字段是必需的”错误。
class PostSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(required=False)
您使用什么视图?如果你使用 GenericAPIView 及其子类,上下文将传递给序列化器,默认 get_serializer_context 将默认传递请求。如果不是,您应该手动传递上下文。
class PostSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(required=False)
def create(self, validated_data):
request = self.context.get('request')
author = Author.objects.get(user=request.user)
# ....
class PostView(mixins.CreateModelMixin, viewsets.GenericViewSet):
serializer_class = PostSerializer
def create(self, request, *args, **kwargs):
super().create(request, *args, **kwargs)
更新:
我错了,有更简单的解决方法:
这应该是最简单的方法。
class PostViewSet(viewsets.ModelViewSet):
# ... other implementations
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data={"author": request.user.author.id, **request.data})
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)
def update(self, request, pk, *args, **kwargs):
try:
post = Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise NotFound("Post doesn't exist.")
if post.author != request.user.author:
raise PermissionDenied('Permission Denied!')
serializer = PostSerializer(post, data={"author": request.user.author.id, **request.data})
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
这是默认方法,除了传递 author
数据。
您可能需要检查用户是否有 author
关系。
在问这个问题之前,我看到了以下链接,但它们对我没有任何帮助:
pass extra arguments to serializer
我有一个作者模型,它有默认 Django 用户模型的外键:
apps/author/models.py
class Author(models.Model):
user = models.OneToOneField(
User,
related_name='author',
on_delete=models.CASCADE,
default="",
)
is_author = models.BooleanField(
default=True,
)
full_name = models.CharField(
max_length=100,
default="",
)
def __str__(self):
return self.user.username
Post 模型有指向 Author 的外键。
apps/posts/models.py
class Post(models.Model):
author = models.ForeignKey(
Author,
related_name="posts",
on_delete=models.CASCADE,
)
title = models.TextField(
null=True,
blank=True,
)
content = models.TextField(
null=True,
blank=True,
)
is_draft = models.BooleanField(
default=True
)
created_at = models.DateTimeField(
auto_now_add=True,
null=True,
)
published_at = models.DateField(
null=True,
blank=True,
default=None,
)
def __str__(self):
return str(self.id) + ", " + self.title
问题定义: 为了创建一个新的 post,我在视图中从 self.request.user
获取当前用户,并将其传递给Post序列化器。但是每当我想使用以下对 localhost:8000/posts/
的请求创建一个新的 post 时,我都会遇到错误:
# I also added JWT authorization header to the postman! and it doesn't have any problem at this level
{
"title": "",
"content": ""
}
错误
这是我在 apps/posts/views.py
中所做的:
def get_serializer_context(self):
context = super().get_serializer_context()
context["user"] = self.request.user
context["author"] = Author.objects.get(user=context["user"])
print(context["author"])
return context
print(context["author"])
运行良好并打印出当前作者。问题是我无法在序列化程序中获取它。
class PostSerializer(serializers.ModelSerializer):
# author = serializers.SerializerMethodField('get_author')
#
# def get_author(self, obj):
# print('current author', self.context["author"])
# return self.context["author"]
class Meta:
model = Post
fields = '__all__'
extra_fields = ['author']
#def create(self, validated_data):
#print(self.context["author"])
#print(self.context)
PS: 评论是我试过的方法,还是报错。我该如何解决这个问题?
也许你应该在 PostSerializer 的作者字段中添加“required=False”,这将避免“此字段是必需的”错误。
class PostSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(required=False)
您使用什么视图?如果你使用 GenericAPIView 及其子类,上下文将传递给序列化器,默认 get_serializer_context 将默认传递请求。如果不是,您应该手动传递上下文。
class PostSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(required=False)
def create(self, validated_data):
request = self.context.get('request')
author = Author.objects.get(user=request.user)
# ....
class PostView(mixins.CreateModelMixin, viewsets.GenericViewSet):
serializer_class = PostSerializer
def create(self, request, *args, **kwargs):
super().create(request, *args, **kwargs)
更新:
我错了,有更简单的解决方法:
这应该是最简单的方法。
class PostViewSet(viewsets.ModelViewSet):
# ... other implementations
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data={"author": request.user.author.id, **request.data})
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)
def update(self, request, pk, *args, **kwargs):
try:
post = Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise NotFound("Post doesn't exist.")
if post.author != request.user.author:
raise PermissionDenied('Permission Denied!')
serializer = PostSerializer(post, data={"author": request.user.author.id, **request.data})
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
这是默认方法,除了传递 author
数据。
您可能需要检查用户是否有 author
关系。