Python Django REST序列化程序和自定义模型字段中的额外属性
如何将额外属性从自定义模型字段传递到序列化程序 例如,我有一个自定义模型字段RsTestField,它有一个额外的属性“info”,该属性为True或False:Python Django REST序列化程序和自定义模型字段中的额外属性,python,django,rest,django-rest-framework,Python,Django,Rest,Django Rest Framework,如何将额外属性从自定义模型字段传递到序列化程序 例如,我有一个自定义模型字段RsTestField,它有一个额外的属性“info”,该属性为True或False: class RsTestField(models.Field): __metaclass__ = models.SubfieldBase def get_internal_type(self): return "CharField" def __init__(self, info=Fals
class RsTestField(models.Field):
__metaclass__ = models.SubfieldBase
def get_internal_type(self):
return "CharField"
def __init__(self, info=False, *args, **kwargs):
self.info = info
super(RsTestField, self).__init__(*args, **kwargs)
def is_info(self):
return self.info
在以下模型中使用,我可以在其中传递此自定义属性的值:
class Client(models.Model):
test1 = RsTestField(max_length=255, info=True, default="")
name1 = models.CharField(max_length=255, default="")
和以下序列化程序:
class ClientSerializer(serializers.HyperlinkedModelSerializer):
test1 = ModelField(model_field=Client()._meta.get_field('test1'))
class Meta:
model = Client
fields = ('name1','test1')
我希望能够访问test1 info属性,就像访问name1-max_length属性一样
这可能吗
目标是最终在Scheme overview中传递此属性,该属性可通过选项http请求检索:
"actions": {
"POST": {
"name1": {
"type": "string",
"required": false,
"read_only": false,
"label": "Client name 1",
"max_length": 255
},
"test1": {
"type": "field",
"required": true,
"read_only": false,
"label": "Test1"
}
}
}
在“test1”中,应该有一个额外的键:
"info": True
问题1:
我希望能够像访问test1 info属性一样访问它
能够访问name1-max_length属性
是的,您可以通过ModelField.model\u field.info
访问您的info
属性。
您可以看到下面的示例
最后目标的问题2:
我认为您可以自定义自己的元数据类
from rest_framework.metadata import SimpleMetadata
from rest_framework.serializers import ModelField
from pbweb.models import RsTestField
class MyMetadata(SimpleMetadata):
def get_field_info(self, field):
field_info = super(MyMetadata, self).get_field_info(field)
# I will add the info field only for RsTestField-ModelField
if isinstance(field, ModelField) and isinstance(field.model_field, RsTestField):
# access your info attribute HERE
field_info['info'] = field.model_field.info
return field_info
另外,不要忘记配置您的默认元数据\u类
设置
设置.py
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.MyMetadata'
}
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.RsMetaData'
}
好的,我明白了,每个人都在尝试同样的方法,向django模型添加额外的Kwarg,将它们传递给rest_框架序列化程序,并将它们传递给元数据方案,以便在API请求中的OPTIONS方法中获取它们: 在本例中,我将kwarg“serial”添加到CharField。首先扩展django.db.models.CharField并在模型中使用它: models.py 然后为新字段类型创建一个新的序列化程序,例如:下面的RsCharField,并扩展ModelSerializer以创建从Django模型RsCharField到序列化程序RsCharField的映射 扩展ModelSerializer的build_standard_field方法,将django模型RsCharField中的额外Kwarg添加到Serializer RsCharField中 序列化程序.py 最后扩展SimpleMetadata,将新的KWARG传递给api的OPTIONS方法,并在方案中显示:
class RsMetaData(SimpleMetadata):
def get_field_info(self, field):
field_info = super(RsMetaData, self).get_field_info(field)
if(isinstance(field, RsCharField)):
field_info['serial'] = field.serial
return field_info
并调整settings.py
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.MyMetadata'
}
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.RsMetaData'
}
可能还不太整洁,但这就是想法。Tnx苏oooot 您不希望
info
成为数据库中RsTestField
的实际字段(列)?不,我想添加几个描述方案字段的参数,以便前端可以使用它们来构建GUI。e、 g:“info”将标记一个只读字段或信息字段(我知道,已经有一个只读参数),例如一个序列号,它将指示GUI布局中的顺序/指示选项卡停止。1在顶部/第一个,2在该/下一个选项卡下面,等等。所以它们不是数据,它们在前端描述了我的模型字段。啊,这很有意义。谢谢,这非常有效!我的看法是错误的,我一直试图在序列化程序级别而不是元数据级别访问自定义属性。在序列化程序级别,某些数据(如传递给模型字段get的某些KWARG)被丢弃,并且只允许/处理特定的KWARG(因为该类型的字段并不总是需要它们,例如字符串的小数点)Ahh。。它只对CharField这样的显式字段丢弃,而不是自定义子类模型。字段类型。在那里,可以通过model_字段访问它们。Tnx,今天学到了更多。有没有一种方法可以向models.CharField(例如,而不是models.Field)添加额外的属性,以便序列化程序能够看到它们?(就像我前面提到的,似乎在MyCustomField中对CharFields进行子类化,最终在将额外属性传递给序列化程序时将其删除)@squiggy尝试扩展models.CharField和CharField序列化程序怎么样。如果要使用ModelSerilizer,还必须对其进行扩展,并更改序列化器\字段\映射
属性。呃…这很复杂…@squiggy DRF的工作原理是这样的:serializer.Field
从models.Field
获取属性,并将其存储在serializer.Field
中,这些属性因serializer.Field的不同而不同,选项方法即元数据
,直接从serializer.Field
获取属性。如果要对相关字段(如ModelsSerializer中的PrimaryKeyRelatedField)执行相同操作,请在serializers.ModelSerializer.seriliazer_related_字段创建映射,并重写build_relational_字段()ModelSerializer的方法假设这两行serializer\u field\u mapping=serializers.ModelSerializer.serializer\u field\u mapping;serializer_field_mapping[myapp.models.RsCharField]=RsCharField
还将修改serializer.ModelSerializer
类中的字典serializer_field_mapping
,这是不需要的副作用。也许最好在第一行复制一份。