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

2024-10-01 11:22:47 发布

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

如何将自定义模型字段中的额外属性传递给序列化程序?在

例如,我有一个自定义模型字段RsTestField,它有一个额外的属性“info”,它是真是假:

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

它在以下模型中使用,我可以在其中传递此自定义属性的值:

^{pr2}$

以及以下序列化程序:

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属性一样。在

这可能吗?在

目标是最终在方案概述中传递此属性,可以使用选项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

Tags: 模型self程序infoclientfalsefield属性
2条回答

问题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:

我认为您可以自定义自己的元数据类。在

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设置

在设置.py在

^{pr2}$

好了,每个人都在尝试同样的方法,向django模型添加额外的kwarg,将它们传递给rest_framework序列化程序,并将它们传递到元数据方案中,以便在API请求的OPTIONS方法中获取它们:

在这个例子中,我向CharField添加了一个kwarg'serial'。第一次延伸django.db.型号.CharField并在模型中使用它:

模型.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模型RsCharField到序列化器RsCharField的映射。在

扩展ModelSerializer的build_standard_field方法,以将django模型RsCharField中的额外kwarg添加到序列化程序RsCharField中

序列化程序.py

^{pr2}$

最后,扩展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

然后调整设置.py在

REST_FRAMEWORK = {
    'DEFAULT_METADATA_CLASS': 'my.customize.RsMetaData'
}

可能还不整洁,但这是个主意。太棒了!在

相关问题 更多 >