Django REST serial analyzer and optional attributes from custom model fields

How to pass additional attributes from my custom model field to serializer?

For example, I have this custom field of the RsTestField model, which has an additional “information” attribute, which is True or 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

Used in the following model, where I can pass the value of this custom attribute:

class Client(models.Model):

    test1 = RsTestField(max_length=255, info=True, default="")
    name1 = models.CharField(max_length=255, default="")

And the following serializer:

class ClientSerializer(serializers.HyperlinkedModelSerializer):

    test1 = ModelField(model_field=Client()._meta.get_field('test1'))

    class Meta:
        model = Client
        fields = ('name1','test1')

I want to have access to the test1-info attribute in the same way as I could access the name1-max_length attribute.

Is it possible?

The goal is to eventually pass this attribute to the Schema overview, which can be obtained using the OPTIONS http request:

"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"
        }
    }
}

An additional key should appear in "test1":

"info": True
+4
2

1:

test1-info , name1-max_length.

, info ModelField.model_field.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

settings.py

REST_FRAMEWORK = {
    'DEFAULT_METADATA_CLASS': 'my.customize.MyMetadata'
}
+1

, , , kwargs django, rest_framework , OPTIONS API:

kwarg 'serial' CharField. 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, serializer-RsCharField.

build_standard_field ModelSerializer, kwargs django-model-RsCharField -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 OPTIONS api :

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 soooooot!

0

All Articles