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

Posted

技术标签:

【中文标题】在模型序列化器中获取当前用户【英文标题】:Get current user in Model Serializer 【发布时间】:2015-03-12 03:46:40 【问题描述】:

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

我的模特:

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

如何访问该变量?我已经进行了类似的设置,但是在 create() 方法中,我似乎无法访问该变量。它也不在 request.POST 中。 我使用了上面的代码,但给出了以下错误文件“/Users/abc/abc/Django/Work/abc/abc/src/MadhaparGamApps/serializers/newsfeedSerializer.py”,第 21 行,在 _user 用户中= self.context['request'].user KeyError: 'request' 对于每个收到请求的人 KeyError:您可以通过使用请求对象从视图初始化序列化程序来解决此问题,如下所示:serializer = serializers.RandomSerializer(data=request.data, context= 'request':request) 来源:django-rest-framework.org/api-guide/serializers/… @Braden Holt 谢谢老兄,你为我节省了很多时间 你知道DRF在其源代码的序列化器上下文中插入请求信息的位置吗??【参考方案2】:

一个上下文被传递给 REST 框架中的序列化器,默认情况下它包含请求。所以你可以在你的序列化器中使用self.context['request'].user

【讨论】:

你知道DRF在其源代码的序列化器上下文中插入请求信息的位置吗?? 这不再是真的,您需要将额外的上下文传递给序列化程序。见django-rest-framework.org/api-guide/serializers/… @Akshay Strange,它仍然适用于我,而无需从 DRF 3.9.4 明确传递上下文。【参考方案3】:

我遇到了类似的问题 - 我试图保存包含用户的模型,当我尝试使用 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

【讨论】:

【参考方案4】:

我修改了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

【讨论】:

以上是关于在模型序列化器中获取当前用户的主要内容,如果未能解决你的问题,请参考以下文章

在其他反序列化器中调用自定义 Jackson 反序列化器

Powershell获取当前机器的序列号用户名域

PowerShell获取当前机器的序列号 用户名 域

Django Rest Framework - 在序列化程序中获取相关模型字段

如何在 DRF 中序列化自定义用户模型

无法在 Django Rest Framework 序列化程序的验证数据中获取非模型字段