Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django REST序列化程序和自定义模型字段中的额外属性_Python_Django_Rest_Django Rest Framework - Fatal编程技术网

Python Django REST序列化程序和自定义模型字段中的额外属性

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

如何将额外属性从自定义模型字段传递到序列化程序

例如,我有一个自定义模型字段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')
我希望能够访问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
,这是不需要的副作用。也许最好在第一行复制一份。