在模型序列化器中获取当前用户

问题描述 投票:0回答:5

是否可以在模型序列化器中获取当前用户?我希望这样做而不必脱离泛型,因为这是一项必须完成的简单任务。

我的型号:

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
}
python django serialization django-rest-framework
5个回答
91
投票

我通过查看 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
    }
)

68
投票

REST框架中,上下文被传递给序列化器,默认情况下包含请求。所以你可以在序列化器中使用

self.context['request'].user


4
投票

我有一个类似的问题 - 我尝试保存包含用户的模型,当我尝试使用

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

0
投票

实际上,执行此操作的新方法是使用

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

-2
投票

我修改了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
© www.soinside.com 2019 - 2024. All rights reserved.