在mixin中的Django rest framework modelserializer(只写&读写)中添加添加字段

在mixin中的Django rest framework modelserializer(只写&读写)中添加添加字段,django,django-rest-framework,Django,Django Rest Framework,我想为Modelserializer中的其他字段创建一个mixin。 请参考下面的代码 class AdditionalFieldsMixin(object): additional_fields = dict() def __init__(self, *args, **kwargs): super(AdditionalFieldsMixin, self).__init__(*args, **kwargs) for field_name, fie

我想为Modelserializer中的其他字段创建一个mixin。 请参考下面的代码

class AdditionalFieldsMixin(object):
    additional_fields = dict()

    def __init__(self, *args, **kwargs):
        super(AdditionalFieldsMixin, self).__init__(*args, **kwargs)
        for field_name, field_instance in self.additional_fields.items():
            self.fields[field_name] = field_instance
        print(self.fields)

    def additional_field_before_create(self, additional_field_data):
        pass

    def additional_field_after_create(self, additional_field_data, instance):
        pass

    def additional_field_before_update(self, additional_field_data):
        pass

    def additional_field_after_update(self, additional_field_data, instance):
        pass

    def create(self, validated_data):
        additional_field_data = {}

        for additional_field in self.additional_fields.keys():
            additional_field_data[additional_field] = validated_data.pop(additional_field, None)

        self.additional_field_before_create(additional_field_data)
        instance = super(AdditionalFieldsMixin, self).create(validated_data)
        self.additional_field_after_create(additional_field_data, instance)
        return instance

    def update(self, instance, validated_data):
        additional_field_data = {}

        for additional_field in self.additional_fields.keys():
            additional_field_data[additional_field] = validated_data.pop(additional_field, None)

        self.additional_field_before_update(additional_field_data)
        instance = super(AdditionalFieldsMixin, self).update(instance, validated_data)
        self.additional_field_after_update(additional_field_data, instance)
        return instance
在主课堂上,我宣布

additional_fields = dict(
        reference=CharField(write_only=True, allow_blank=True, allow_null=True, default=None),
    )
但在列表模式下检索数据时,它会给我一个错误

AssertionError: It is redundant to specify `source='reference'` on field 'CharField' in serializer 'MySerializer', because it is the same as the field name. Remove the `source` keyword argument.
为什么会这样? 我还注意到,在第一次启动runserver之后,它不会给出那个错误,但如果我再次查询,它会给出第二次错误,以此类推

还有一个一般性问题

在seialiser mixin类中添加字段的正确方法是什么?
i、 e self.fields[field\u name]=field\u实例是正确的方法吗?

您可以这样做,因为如果您使用Modelializer,您不能请求

class Name(serializers.Serializer):
    name = serializers.CharField(required=True)
    ...
    
    def create(self, validated_data):
        ...
    def update(self, instance, validated_data):
        ...

可以这样做,因为如果使用Modelializer,则无法请求

class Name(serializers.Serializer):
    name = serializers.CharField(required=True)
    ...
    
    def create(self, validated_data):
        ...
    def update(self, instance, validated_data):
        ...

Modelserializer上的额外读写字段

额外的读和写字段必须从模型实例派生,以便您可以在模型上添加
@property
def reference
,并在序列化程序中将字段声明为

reference = CharField(source='reference')
reference = CharField(write_only=True)
并从覆盖modelserializer的创建更新的验证数据中弹出字段数据

简而言之,在直接代码中很难实现额外的读写字段,但这是可能的。

Modelserializer上的额外只读字段

SerializerMethodField
ReadOnlyField
source
参数一起使用,或与上述代码类似的
readonly=True
参数一起使用。e、 g

reference = CharField(source='reference', read_only=True)
Modelserializer上的额外只写字段(必选答案)

将mainserializer上的字段写入为

reference = CharField(source='reference')
reference = CharField(write_only=True)
如果没有问题,该字段将显示在
创建
更新
中的验证数据中 覆盖它们,弹出字段,做你想做的事情,用新的验证数据调用
super()

按照问题中的要求进行混音(对于只写字段)

事实证明,您可以重写序列化程序的
to_internal_value
方法并向其添加字段。序列化程序保存数据(创建、更新)时会调用
to_internal_值
,因此您可以按如下方式覆盖它

def to_internal_value(self, data):
    for field_name, field_instance in self.additional_write_only_fields.items():
        self.fields[field_name] = field_instance
    return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)
class AdditionalWriteOnlyFieldsMixin(object):
    additional_write_only_fields = dict()

    def to_internal_value(self, data):
        for field_name, field_instance in self.additional_write_only_fields.items():
            self.fields[field_name] = field_instance
        return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)

    def additional_fields_before_create(self, additional_data):
        pass

    def additional_fields_after_create(self, additional_data, instance):
        pass

    def additional_fields_before_update(self, additional_data):
        pass

    def additional_fields_after_update(self, additional_data, instance):
        pass

    def create(self, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_create(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).create(validated_data)
        self.additional_fields_after_create(additional_data, instance)
        return instance

    def update(self, instance, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_update(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).update(instance, validated_data)
        self.additional_fields_after_update(additional_data, instance)
        return instance
这将解决向模型序列化程序添加许多只写字段的问题。这就是我创建mixin的原因,如下所示

def to_internal_value(self, data):
    for field_name, field_instance in self.additional_write_only_fields.items():
        self.fields[field_name] = field_instance
    return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)
class AdditionalWriteOnlyFieldsMixin(object):
    additional_write_only_fields = dict()

    def to_internal_value(self, data):
        for field_name, field_instance in self.additional_write_only_fields.items():
            self.fields[field_name] = field_instance
        return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)

    def additional_fields_before_create(self, additional_data):
        pass

    def additional_fields_after_create(self, additional_data, instance):
        pass

    def additional_fields_before_update(self, additional_data):
        pass

    def additional_fields_after_update(self, additional_data, instance):
        pass

    def create(self, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_create(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).create(validated_data)
        self.additional_fields_after_create(additional_data, instance)
        return instance

    def update(self, instance, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_update(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).update(instance, validated_data)
        self.additional_fields_after_update(additional_data, instance)
        return instance
因此,在modelserializer类中包含mixin,并将
附加的\u只写\u字段
声明为dict,将key作为字段名,将value作为字段实例,并重写
附加的\u字段*
函数以实现所需的功能,例如

class MySerializer(AdditionalWriteOnlyFieldsMixin, ModelSerializer):
    additional_write_only_fields = dict(
        reference=CharField(write_only=True, allow_blank=True, allow_null=True, default=None),
    )
    
    def additional_fields_after_create(self, additional_data, instance):
        print(additional_data)
        
    class Meta:
        model=MyModel
        fields='__all__'
附加注释

您还可以重写序列化程序的
to_表示法
方法,以添加只读字段,或者将
to_表示法
to_内部值
组合起来,以创建额外的读写字段!。但是我离开这个工作去另一个答案,呃

参考资料


Modelserializer上的额外读写字段

额外的读和写字段必须从模型实例派生,以便您可以在模型上添加
@property
def reference
,并在序列化程序中将字段声明为

reference = CharField(source='reference')
reference = CharField(write_only=True)
并从覆盖modelserializer的创建更新的验证数据中弹出字段数据

简而言之,在直接代码中很难实现额外的读写字段,但这是可能的。

Modelserializer上的额外只读字段

SerializerMethodField
ReadOnlyField
source
参数一起使用,或与上述代码类似的
readonly=True
参数一起使用。e、 g

reference = CharField(source='reference', read_only=True)
Modelserializer上的额外只写字段(必选答案)

将mainserializer上的字段写入为

reference = CharField(source='reference')
reference = CharField(write_only=True)
如果没有问题,该字段将显示在
创建
更新
中的验证数据中 覆盖它们,弹出字段,做你想做的事情,用新的验证数据调用
super()

按照问题中的要求进行混音(对于只写字段)

事实证明,您可以重写序列化程序的
to_internal_value
方法并向其添加字段。序列化程序保存数据(创建、更新)时会调用
to_internal_值
,因此您可以按如下方式覆盖它

def to_internal_value(self, data):
    for field_name, field_instance in self.additional_write_only_fields.items():
        self.fields[field_name] = field_instance
    return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)
class AdditionalWriteOnlyFieldsMixin(object):
    additional_write_only_fields = dict()

    def to_internal_value(self, data):
        for field_name, field_instance in self.additional_write_only_fields.items():
            self.fields[field_name] = field_instance
        return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)

    def additional_fields_before_create(self, additional_data):
        pass

    def additional_fields_after_create(self, additional_data, instance):
        pass

    def additional_fields_before_update(self, additional_data):
        pass

    def additional_fields_after_update(self, additional_data, instance):
        pass

    def create(self, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_create(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).create(validated_data)
        self.additional_fields_after_create(additional_data, instance)
        return instance

    def update(self, instance, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_update(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).update(instance, validated_data)
        self.additional_fields_after_update(additional_data, instance)
        return instance
这将解决向模型序列化程序添加许多只写字段的问题。这就是我创建mixin的原因,如下所示

def to_internal_value(self, data):
    for field_name, field_instance in self.additional_write_only_fields.items():
        self.fields[field_name] = field_instance
    return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)
class AdditionalWriteOnlyFieldsMixin(object):
    additional_write_only_fields = dict()

    def to_internal_value(self, data):
        for field_name, field_instance in self.additional_write_only_fields.items():
            self.fields[field_name] = field_instance
        return super(AdditionalWriteOnlyFieldsMixin, self).to_internal_value(data)

    def additional_fields_before_create(self, additional_data):
        pass

    def additional_fields_after_create(self, additional_data, instance):
        pass

    def additional_fields_before_update(self, additional_data):
        pass

    def additional_fields_after_update(self, additional_data, instance):
        pass

    def create(self, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_create(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).create(validated_data)
        self.additional_fields_after_create(additional_data, instance)
        return instance

    def update(self, instance, validated_data):
        additional_data = {key: validated_data.pop(key, None) for key in self.additional_write_only_fields.keys()}
        self.additional_fields_before_update(additional_data)
        instance = super(AdditionalWriteOnlyFieldsMixin, self).update(instance, validated_data)
        self.additional_fields_after_update(additional_data, instance)
        return instance
因此,在modelserializer类中包含mixin,并将
附加的\u只写\u字段
声明为dict,将key作为字段名,将value作为字段实例,并重写
附加的\u字段*
函数以实现所需的功能,例如

class MySerializer(AdditionalWriteOnlyFieldsMixin, ModelSerializer):
    additional_write_only_fields = dict(
        reference=CharField(write_only=True, allow_blank=True, allow_null=True, default=None),
    )
    
    def additional_fields_after_create(self, additional_data, instance):
        print(additional_data)
        
    class Meta:
        model=MyModel
        fields='__all__'
附加注释

您还可以重写序列化程序的
to_表示法
方法,以添加只读字段,或者将
to_表示法
to_内部值
组合起来,以创建额外的读写字段!。但是我离开这个工作去另一个答案,呃

参考资料