在Django序列化程序中,从上下文(或请求数据)获取默认字段值

2024-09-27 22:20:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我在REST框架中使用Django。在序列化程序中,我希望根据视图或请求(request.data['type'])参数分配字段值,因此我需要上下文中的视图/请求。在

我成功了,但只是以一种笨拙的方式,我正在寻找简化代码的方法。以下是成功的方法(省略无关字段):

class TypeDefault(object):
    def set_context(self, serializer_field):
        view = serializer_field.context['view'] # or context['request']

        self.type = view.kwargs['type'].upper()

    def __call__(self):
        return self.type


class RRsetSerializer(serializers.ModelSerializer):
    type = serializers.CharField(read_only=True, default=serializers.CreateOnlyDefault(TypeDefault()))

    class Meta:
        model = RRset
        fields = ('type',)
        read_only_fields = ('type',)

为了简化操作,我尝试删除TypeDefault类,并将type序列化程序字段替换为

^{pr2}$

但是,context.get('view')返回None。我不确定为什么视图上下文在这里不可用。我的印象是,不需要额外的类就可以获得所需的功能。在

作为奖励,最好在字段声明中指定默认值,比如

    type = serializers.CharField(default=self.context.get('view').kwargs['type'].upper())

但是,self在这里没有定义,我不确定什么是正确的方法。在


另外,我对从视图或从请求数据中检索信息是否有任何不同感兴趣。虽然上下文方法应该同时适用于这两者,但是当值从请求数据中获得时,也许有一种更简单的方法来获得CreateOnlyDefault功能,因为序列化程序无论如何都会处理请求数据。在


编辑:根据Geotob的请求,下面是调用序列化程序的视图代码:

class RRsetsDetail(generics.ListCreateAPIView):
    serializer_class = RRsetSerializer
    # permission_classes = ... # some permission constraints

    def get_queryset(self):
        name = self.kwargs['name']
        type = self.kwargs.get('type')

        # Note in the following that the RRset model has a `domain` foreign-key field which is referenced here. It is irrelevant for the current problem though.
        if type is not None:
            return RRset.objects.filter(domain__name=name, domain__owner=self.request.user.pk, type=type)
        else:
            return RRset.objects.filter(domain__name=name, domain__owner=self.request.user.pk)

urls.py中,我有(除其他外):

url(r'^domains/(?P<name>[a-zA-Z\.\-_0-9]+)/rrsets/$', RRsetsDetail.as_view(), name='rrsets'),
url(r'^domains/(?P<name>[a-zA-Z\.\-_0-9]+)/rrsets/(?P<type>[A-Z]+)/$', RRsetsDetail.as_view(), name='rrsets-type'),

Tags: 方法nameself程序view视图序列化request
2条回答

^{}是一个只读字段,因此我认为除非您设置默认值,否则它将无法工作。。。你又回到了与CharField相同的问题。在

简单来说,你可以摆脱serializers.CreateOnlyDefault

class RRsetSerializer(serializers.ModelSerializer):
    type = serializers.CharField(read_only=True, default=TypeDefault())

如果你想要更具活力的东西,我只能这样想:

^{pr2}$

FromContext在实例化期间接受一个函数,该函数将用于从上下文中检索所需的值。在

总之,上述第二种方法是正确的:

使用serializers.SerializerMethodField并从序列化程序方法访问self.context

class SomeSerializer(serializers.ModelSerializer):
    type = serializers.SerializerMethodField()

    def get_type(self, obj):
        return self.context['view'].kwargs['type'].upper()

viewrequestformat键由所有DRF通用视图自动添加到序列化程序上下文中(本节末尾的http://www.django-rest-framework.org/api-guide/generic-views/#methods)。这个很好用。在

如果您要手动创建序列化程序实例,则必须将context=contextDict作为参数传递,其中contextDict是您需要的值(http://www.django-rest-framework.org/api-guide/serializers/#including-extra-context)。在

正如@Michael在另一个答案中指出的,SerializerMethodField将是只读的。但是根据您的第一个示例(type = serializers.CharField(read_only=True.....),这似乎是您想要的。在

相关问题 更多 >

    热门问题