是否可以在模型序列化器中获取当前用户?我希望这样做而不必脱离泛型,因为这是一项必须完成的简单任务。
我的型号:
class Activity(models.Model):
number = models.PositiveIntegerField(
blank=True, null=True, help_text="Activity number. For record keeping only.")
instructions = models.TextField()
difficulty = models.ForeignKey(Difficulty)
categories = models.ManyToManyField(Category)
boosters = models.ManyToManyField(Booster)
class Meta():
verbose_name_plural = "Activities"
我的序列化器:
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
我的观点:
class ActivityDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Activity.objects.all()
serializer_class = ActivityDetailSerializer
如何返回模型,并带有附加字段
user
,这样我的回复如下所示:
{
"id": 1,
"difficulty": 1,
"categories": [
1
],
"boosters": [
1
],
"current_user": 1 //Current authenticated user here
}
我通过查看 DRF 源代码找到了答案。
class ActivitySerializer(serializers.ModelSerializer):
# Create a custom method field
current_user = serializers.SerializerMethodField('_user')
# Use this method for the custom field
def _user(self, obj):
request = self.context.get('request', None)
if request:
return request.user
class Meta:
model = Activity
# Add our custom method to the fields of the serializer
fields = ('id','current_user')
关键是,
ModelSerializer
内定义的方法可以访问它们自己的上下文,其中始终包含请求(当用户经过身份验证时,其中包含用户)。由于我的权限仅适用于经过身份验证的用户,因此这里应该始终有一些东西。
这也可以在其他内置 djangorestframework 序列化器中完成。
正如 Braden Holt 指出的那样,如果您的
user
仍然为空(即 _user
返回 None
),可能是因为序列化器未使用请求作为上下文的一部分进行初始化。要解决此问题,只需在初始化序列化器时添加请求上下文即可:
serializer = ActivitySerializer(
data=request.data,
context={
'request': request
}
)
REST框架中,上下文被传递给序列化器,默认情况下包含请求。所以你可以在序列化器中使用
self.context['request'].user
。
我有一个类似的问题 - 我尝试保存包含用户的模型,当我尝试使用
user = serializers.StringRelatedField(read_only=True, default=serializers.CurrentUserDefault())
就像官方文档一样 - 但它会抛出一个错误,指出用户是 'null'
。重写默认的 create
方法并从请求中获取用户对我有帮助:
class FavoriteApartmentsSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True, default=serializers.CurrentUserDefault())
class Meta:
model = FavoriteApartments
exclude = (
'date_added',
)
def create(self, validated_data):
favoriteApartment = FavoriteApartments(
apartment=validated_data['apartment'],
user=self.context['request'].user
)
favoriteApartment.save()
return favoriteApartment
实际上,执行此操作的新方法是使用
HiddenField
-
查看 drf 文档:
class ReportSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Report
fields = ('id', 'type', 'name', 'post', 'comment', "author")
执行此操作时,请务必将
isAuthenticated
添加到权限类,否则保存时会出错。
但是,如果它是可选的,只需使用文档中的示例创建您自己的类。
因此只需将
required
设置为 false
即可使该字段可选,
然后创建你自己的类:
class CurrentUserDefault:
requires_context = True
def __call__(self, serializer_field):
if serializer_field.context['request'].is_authenticated:
return None
return serializer_field.context['request'].user
我修改了request.data:
serializer = SectionSerializer(data=add_profile_data(request.data, request.user))
def add_profile_data(data, user):
data['user'] = user.profile.id
return data