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

Python 在Django序列化程序中,如何基于视图参数设置外键字段?,python,django,serialization,django-rest-framework,Python,Django,Serialization,Django Rest Framework,使用Django REST框架,我希望允许用户通过ListCreateAPIView(通过POST)创建和保存Django模型的实例。其中一个字段(外键字段称为domain)应根据url.py中定义的视图参数确定 此外,用户可以在以后使用PUT或PATCH请求对RetrieveUpdateDestroyAPIView端点修改模型实例(使用相同的序列化程序)。我不希望用户此时能够修改域字段 虽然我已经准备好了模型和视图/序列化程序结构的代码,但我不知道如何告诉序列化程序根据view参数确定域字段的

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

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

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

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)
。。。和一个直接的
列表CreateApiView

class RRsetsDetail(generics.ListCreateAPIView):
    serializer_class = RRsetSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_queryset(self):
        name = self.kwargs['name']
        return RRset.objects.filter(domain__name=name, domain__owner=self.request.user.pk)
url.py
包含以下行:

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

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

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

    我想您要找的是一个具有

    HiddenField

    一个字段类,它不基于用户输入获取值,而是从默认值或可调用值获取值

    CreateOnlyDefault

    一个默认类,在运行期间只能用于设置默认参数 创建操作。在更新过程中,该字段被忽略

    它只接受一个参数,即默认值或可调用参数 在创建操作期间应使用的

    因为您想要访问视图,所以不能只使用callable,而是必须使用callable,它可以访问上下文数据

    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()))
    

    谢谢,这看起来很有希望。但是,我得到了以下错误(| |由我,表示换行):回溯(最近一次调用最后一次):[…]文件/usr/local/lib/python3.5/site packages/rest_framework/fields.py”,第257行,在set|context | self.default.set_context(serializer|field)| TypeError:set_context()缺少1个必需的位置参数:“serializer_field”我无法找出问题所在。您知道吗?实例化
    DomainDefault
    类,即使用
    DomainDefault()
    而不仅仅是
    DomainDefault
    。我会更新答案的。
    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()))