【问题标题】:How to make a field editable on create and read-only on update in Django REST framework如何在Django REST框架中使字段在创建时可编辑并在更新时只读
【发布时间】:2019-04-16 19:13:20
【问题描述】:

我想实现一种 Django 模型的常量字段。我希望在创建模型实例时设置该字段(通过 REST 框架 API),但在更新此字段时必须禁止更改。在 Django 本身或 REST 框架序列化程序选项中是否有一种优雅的方法?

【问题讨论】:

标签: django django-rest-framework


【解决方案1】:

覆盖序列化器中的更新方法并移除该字段:

class MySerializer(serializers.ModelSerializer):        
    def update(self, instance, validated_data):
        validated_data.pop('myfield', None)  # prevent myfield from being updated
        return super().update(instance, validated_data)

【讨论】:

    【解决方案2】:

    上述两种解决方案都有效,但创建可扩展方法来控制任何 CRUD 操作的修改权限的好方法如下:

    1. 创建基本序列化程序类:BaseSerializer
    2. 在所有序列化程序类中从此类继承

    基本序列化程序类中的控件:

    class BaseSerializer(DynamicFieldsSerializer):
        # This overrides a built-in base class method
        def get_extra_kwargs(self):
            """Add additional constraints between CRUD methods to
            any particular field
    
            NB: Use the same extra_kwags dict object in all method calls
            - important to make changes on central object
            """
            extra_kwargs_for_edit = super().get_extra_kwargs()
            
            # Example of making uuid only editable on create, not update 
            self.add_create_only_constraint_to_field("uuid", extra_kwargs_for_edit)
            return extra_kwargs_for_edit
    
        def add_create_only_constraint_to_field(self, key: str, extra_kwargs: dict) -> dict:
            """Ensures key is only writable on create, not update"""
            action = self.context["view"].action
            if action in ["create"]:
                kwargs = extra_kwargs.get(key, {})
                kwargs["read_only"] = False
                extra_kwargs[key] = kwargs
            elif action in ["update", "partial_update"]:
                kwargs = extra_kwargs.get(key, {})
                kwargs["read_only"] = True
                extra_kwargs[key] = kwargs
    
         # You could add other constraints to CRUD operations here
         # def another_field_constrained_by_crud_method(self, key: str, extra_kwargs: dict) -> dict:
    
    class SomeModelSerializer(BaseSerializer):
        # Your serializer logic here
        pass
    

    感谢Nicholas Coles的回答!

    【讨论】:

      猜你喜欢
      • 2012-11-03
      • 2016-05-01
      • 1970-01-01
      • 2013-07-10
      • 1970-01-01
      • 2017-03-04
      • 2014-07-07
      • 1970-01-01
      • 2019-09-08
      相关资源
      最近更新 更多