Django REST 序列化程序和来自自定义模型字段的额外属性
Django REST serializer and extra attributes from custom model fields
如何将自定义模型字段中的额外属性传递给序列化程序?
例如,我有这个自定义模型字段 RsTestField,它有一个额外的属性 "info",它是 True 或 False:
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')
我希望能够像访问 name1-max_length 属性一样访问 test1-info 属性。
这可能吗?
目标是最终在 Scheme 概述中传递此属性,可以使用 OPTIONS 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:
I want to be able to access the test1-info attribute just like i would
be able to access the name1-max_length attribute.
是的,您可以通过 ModelField.model_field.info
访问您的 info
属性。
你可以看下面的例子。
问题 2 的最终目标:
我认为您可以自定义自己的元数据class。
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
并且,不要忘记配置您的 DEFAULT_METADATA_CLASS
设置
settings.py
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.MyMetadata'
}
好的,对于每个尝试相同的人来说,向 django-models 添加额外的 kwargs,将它们传递给 rest_framework 序列化程序,并将它们传递给元数据方案以在 OPTIONS 方法中获取它们API 请求:
在这个例子中,我向 CharField 添加了一个 kwarg 'serial'。首先扩展 django.db.models.CharField 并在模型中使用它:
models.py
class RsCharField(models.CharField, metaclass=models.SubfieldBase):
def __init__(self, serial=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.serial = serial
class MyModel(models.Model):
fied_name1 = RsCharField(max_length=100, serial=123456, default="")
然后为您的新字段类型创建一个新的序列化程序,例如:下面的 RsCharField,并扩展 ModelSerializer 以创建从 Django-model-RsCharField 到序列化程序-RsCharField 的映射。
扩展 ModelSerializer 的 build_standard_field 方法以将额外的 kwargs 从 django-model-RsCharField 添加到 serializers-RsCharField
serializers.py
from rest_framework import serializers
class RsCharField(serializers.CharField):
def __init__(self, serial=None, **kwargs):
self.serial = serial
super().__init__(**kwargs)
class RsModelSerializer(serializers.ModelSerializer):
serializer_field_mapping = serializers.ModelSerializer.serializer_field_mapping
serializer_field_mapping[myapp.models.RsCharField] = RsCharField
def build_standard_field(self, field_name, model_field):
field_class, kwargs = super().build_standard_field(field_name, model_field)
if isinstance(model_field, kernel.fields.RsCharField):
kwargs['serial'] = model_field.serial
return field_class, kwargs
最后扩展 SimpleMetadata 以将新的 kwargs 传递给 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.RsMetaData'
}
可能还不完善,但就是这个想法。 Tnx 太棒了!
如何将自定义模型字段中的额外属性传递给序列化程序?
例如,我有这个自定义模型字段 RsTestField,它有一个额外的属性 "info",它是 True 或 False:
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')
我希望能够像访问 name1-max_length 属性一样访问 test1-info 属性。
这可能吗?
目标是最终在 Scheme 概述中传递此属性,可以使用 OPTIONS 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:
I want to be able to access the test1-info attribute just like i would be able to access the name1-max_length attribute.
是的,您可以通过 ModelField.model_field.info
访问您的 info
属性。
你可以看下面的例子。
问题 2 的最终目标:
我认为您可以自定义自己的元数据class。
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
并且,不要忘记配置您的 DEFAULT_METADATA_CLASS
设置
settings.py
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'my.customize.MyMetadata'
}
好的,对于每个尝试相同的人来说,向 django-models 添加额外的 kwargs,将它们传递给 rest_framework 序列化程序,并将它们传递给元数据方案以在 OPTIONS 方法中获取它们API 请求:
在这个例子中,我向 CharField 添加了一个 kwarg 'serial'。首先扩展 django.db.models.CharField 并在模型中使用它:
models.py
class RsCharField(models.CharField, metaclass=models.SubfieldBase):
def __init__(self, serial=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.serial = serial
class MyModel(models.Model):
fied_name1 = RsCharField(max_length=100, serial=123456, default="")
然后为您的新字段类型创建一个新的序列化程序,例如:下面的 RsCharField,并扩展 ModelSerializer 以创建从 Django-model-RsCharField 到序列化程序-RsCharField 的映射。
扩展 ModelSerializer 的 build_standard_field 方法以将额外的 kwargs 从 django-model-RsCharField 添加到 serializers-RsCharField
serializers.py
from rest_framework import serializers
class RsCharField(serializers.CharField):
def __init__(self, serial=None, **kwargs):
self.serial = serial
super().__init__(**kwargs)
class RsModelSerializer(serializers.ModelSerializer):
serializer_field_mapping = serializers.ModelSerializer.serializer_field_mapping
serializer_field_mapping[myapp.models.RsCharField] = RsCharField
def build_standard_field(self, field_name, model_field):
field_class, kwargs = super().build_standard_field(field_name, model_field)
if isinstance(model_field, kernel.fields.RsCharField):
kwargs['serial'] = model_field.serial
return field_class, kwargs
最后扩展 SimpleMetadata 以将新的 kwargs 传递给 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.RsMetaData'
}
可能还不完善,但就是这个想法。 Tnx 太棒了!