在Django序列化程序中,如何根据视图参数设置外键字段?

2024-09-27 22:19:39 发布

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

使用Django REST框架,我希望允许用户通过ListCreateAPIView(通过POST)来创建和保存Django模型的实例。其中一个字段(外键字段称为domain)应根据urls.py中定义的视图参数确定。在

此外,用户可以稍后使用PUTPATCH请求对RetrieveUpdateDestroyAPIView端点(使用相同的序列化程序)修改模型实例。我不希望用户此时能够修改domain字段。在

虽然我已经准备好了模型和视图/序列化程序结构的代码,但我不确定如何告诉序列化程序根据view参数确定domain字段的值。我得到的是:

class RRset(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(null=True)
    domain = models.ForeignKey(Domain, on_delete=models.CASCADE, related_name='rrsets')
    subname = models.CharField(max_length=255, blank=True)
    type = models.CharField(max_length=10)

。。。还有一个直截了当的ListCreateAPIView

^{pr2}$

urls.py包含以下行:

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

这允许用户使用RRsetsSerializer序列化程序列出并创建RRset对象(列出name字段只是为了完整性,但我不认为它在这个上下文中很重要):

class RRsetSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()

    def get_name(self, obj):
        return '.'.join(filter(None, [obj.subname, obj.domain.name])) + '.' # returns 'subname.name.'

    class Meta:
        model = RRset
        fields = ('created', 'updated', 'domain', 'name', 'type',)
        read_only_fields = ('created', 'updated', 'domain', 'type',)

问题:

  1. 要使序列化程序从视图name参数中获取domain名称,我需要修改什么?在
  2. 序列化程序的read_only_fields设置阻止用户以后修改domain字段。但是,我不确定此设置是否与试图设置默认值的序列化程序交互(即使设置了只读,序列化程序是否可以写入默认值)?在

总而言之:我要找的是类似于“write once字段,该字段具有基于视图参数的默认值”。在


Tags: 用户name模型程序视图true参数序列化
1条回答
网友
1楼 · 发布于 2024-09-27 22:19:39

我想你要找的是HiddenFieldCreateOnlyDefault的组合

HiddenField

A field class that does not take a value based on user input, but instead takes its value from a default value or callable.

CreateOnlyDefault

A default class that can be used to only set a default argument during create operations. During updates the field is omitted.

It takes a single argument, which is the default value or callable that should be used during create operations.

因为您想访问视图,所以不能只使用callable,而是必须使用可以访问上下文数据的Class-basedcallable。在

class DomainDefault(object):
    def set_context(self, serializer_field):
        view = serializer_field.context['view']
        request = serializer_field.context['request']
        self.domain = ...#determine the domain based on request+view

    def __call__(self):
        return self.domain


class RRsetSerializer(serializers.ModelSerializer):
    domain = serializers.HiddenField(default=serializers.CreateOnlyDefault(DomainDefault()))

相关问题 更多 >

    热门问题