Django 序列化程序:为什么 self.fields.pop('field_name') 有效?

Django serializers: why does self.fields.pop('field_name') work?

参考以下 link 作为示例(其他地方还有很多其他示例): http://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields

据了解,Django 序列化程序字段通常使用不可变的元组定义:

class UserSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email')

但是,动态更改序列化程序字段的公认方法涉及使用弹出 (self.fields.pop(field_name))

class DynamicFieldsModelSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

如何定义字段? Django 序列化程序中是否有预处理步骤?

您可以覆盖序列化程序 init 方法并根据查询参数动态设置字段属性。您可以通过传递给序列化程序的上下文访问请求对象。

我在这里创建了一个可重用的 mixin,用于修改动态字段。

从 rest_framework 导入序列化程序

class DynamicFieldsModelSerializer(serializers.ModelSerializer): """ 一个带有额外 fields 参数的 ModelSerializer 控制应显示哪些字段。 """

def __init__(self, *args, **kwargs):
    # Instantiate the superclass normally
    super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

    fields = self.context['request'].QUERY_PARAMS.get('fields')
    if fields:
        fields = fields.split(',')
        # Drop any fields that are not specified in the `fields` argument.
        allowed = set(fields)
        existing = set(self.fields.keys())
        for field_name in existing - allowed:
            self.fields.pop(field_name)


class UserSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email')

查看:

https://github.com/encode/django-rest-framework/blob/3fcc076d9124fc202be1a4379b6b753209c7afbe/rest_framework/serializers.py#L354

def fields(self):
    """
    A dictionary of {field_name: field_instance}.
    """
    # `fields` is evaluated lazily. We do this to ensure that we don't
    # have issues importing modules that use ModelSerializers as fields,
    # even if Django's app-loading stage has not yet run.
    if not hasattr(self, '_fields'):
        self._fields = BindingDict(self)
        for key, value in self.get_fields().items():
            self._fields[key] = value
    return self._fields

How do fields get defined?

现在应该清楚了。

Is there a pre-processing step in Django serializers?

是的。 这个"step"叫做metaclass

并且Serializers、Models、Forms是元类。