序列化程序上的Django verbose_name属性

时间:2017-09-06 15:19:01

标签: python django django-rest-framework

我正在使用django rest框架为angular cli构建一个API后端,我不知道如何访问verbose_name的模型字段属性以便序列化它。这是我的代码:

models.py
class MyModel(model.Models):
    myField = models.CharField(verbose_name='My Verbose Name')
    # Here I have other 30 fields

这是此型号的序列化器

serializers.py
class MyModelSerializer(ModelSerializer):  
    myField = SerializerMethodField()

    def get_myField(self, obj):
        field = next(f for f in obj._meta.fields if f.name == 'myField')
        myField=  {
            'verbose_name': field.verbose_name.title(),
            'value': obj.myField
            }
        return myField
    # Do I Have to repeat this function for every field on my Model in order to have verbose-name ??

    class Meta:
        model = MyModel
        fields = ['nominativo' ]

我的观点是:

class MyModelListAPIView(ListAPIView):
    queryset = Archivio.objects.all()
    serializer_class = MyModelSerializer

我的输出就像我的愿望,就像这样:

[
    {
    "myField":
        {
         "verbose_name":"My Verbose Name",
         "value":"My Field value"
         }
    }
]

但只有少数几个字段就可以了。在我的情况下,我需要有一个这样的输出与我的模型的30个字段。有没有更好的解决方案,而不是在我的get_field类上制作30个ModelSerializer函数?

2 个答案:

答案 0 :(得分:3)

我认为使用字段本身(将表示更改为对象)可能不是实现所需内容的最佳方式(当然不是最简单的方法)。

相反,我会尝试定义我的ModelSerializer,它会自动生成"标签"例如,字段(基本实现):

from rest_framework import serializers
from rest_framework.fields import SerializerMethodField


class MyModelSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(MyModelSerializer, self).__init__(*args, **kwargs)

        if 'labels' in self.fields:
            raise RuntimeError(
                'You cant have labels field defined '
                'while using MyModelSerializer'
            )

        self.fields['labels'] = SerializerMethodField()

    def get_labels(self, *args):
        labels = {}

        for field in self.Meta.model._meta.get_fields():
            if field.name in self.fields:
                labels[field.name] = field.verbose_name

        return labels

然后,如果您使用MyModelSerializer而不是serializers.ModelSerializer,您将获得如下输出:

{
  'name': 'Test',
  'email': 'test@test.com',
  'labels': {
     'name': 'Full name',
     'email': 'Email address'
  }
}

这样,django rest框架生成的所有字段的逻辑保持不变,并且你有一个只读字段。很干净。

答案 1 :(得分:2)

您必须覆盖.to_representation课程的ModelSerializer Docs
Source code

你想要这样的东西(修改后的原始source) -

from rest_framework import serializers
from rest_framework.relations import PKOnlyObject


class MyModelSerializer(serializers.ModelSerializer):

    def to_representation(self, instance):
        """Object instance -> Dict of primitive datatypes."""
        ret = OrderedDict()
        fields = self._readable_fields

        for field in fields:
            try:
                attribute = field.get_attribute(instance)
            except SkipField:
                continue

            # We skip `to_representation` for `None` values so that fields do
            # not have to explicitly deal with that case.
            #
            # For related fields with `use_pk_only_optimization` we need to
            # resolve the pk value.
            check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
            if check_for_none is None:
                value = None
            else:
                value = field.to_representation(attribute)

            ret[field.field_name] = {
                'value': value,
                # You can find more field attributes here
                # https://github.com/encode/django-rest-framework/blob/master/rest_framework/fields.py#L324
                'verbose_name': field.label,
                'read_only': field.read_only,
                'write_only': field.write_only,
                'help_text': field.help_text,
            }

        return ret