13👍
✅
Overwrite the update method in the serializer and remove the field:
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👍
Both above solutions work, but a nice way to create an extensible method for controlling the modify permissions of any CRUD operation is the following:
- Create a base serializer class:
BaseSerializer
- Inherit from this class in all your serializer classes
Control in the base serializer class:
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
Thanks to Nicholas Coles for the answer!
👤Peza
- Django – Check diference between old and new value when overriding save method
- Setting HTTP_REFERER header in Django test
- How to have a nested inline formset within a form in Django?
- Getting a list from Django into Javascript as an array
- Django – Change a ForeignKey relation to OneToOne
0👍
I like to check self.instance
to determine if the serializer is in "create mode" or "update mode". You could also check self.partial
if you want to allow editing the field for non-partial updates.
class MySerializer(Serializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance:
self.fields['create_only_field'].read_only = True
Dynamically modifying the fields from __init__
seems to be officially endorsed by the docs.
👤Ryan
- Django aggregation: sum then average
- How to test a Django on_commit hook without clearing the database?
Source:stackexchange.com