diff options
author | 2023-12-11 18:09:39 +0100 | |
---|---|---|
committer | 2023-12-11 17:09:39 +0000 | |
commit | e8f8161e41a4735897b3038e202107f5d55ec96e (patch) | |
tree | 51998b09ecd506df7562f8eaa564c7154f4bdddc /pydis_site/apps/api/serializers.py | |
parent | Implement editing of offensive message records (#1165) (diff) |
Unify frozen fields logic into serializer mixin (#1169)
Additionally, implement frozen fields on the offensive message
serializer.
Diffstat (limited to 'pydis_site/apps/api/serializers.py')
-rw-r--r-- | pydis_site/apps/api/serializers.py | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 2186b02c..87fd6190 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -2,6 +2,7 @@ from datetime import timedelta from typing import Any +from django.db import models from django.db.models.query import QuerySet from django.db.utils import IntegrityError from rest_framework.exceptions import NotFound @@ -35,6 +36,30 @@ from .models import ( User ) +class FrozenFieldsMixin: + """ + Serializer mixin that allows adding non-updateable fields to a serializer. + + To use, inherit from the mixin and specify the fields that should only be + written to on creation in the `frozen_fields` attribute of the `Meta` class + in a serializer. + + See also the DRF discussion for this feature at + https://github.com/encode/django-rest-framework/discussions/8606, which may + eventually provide an official way to implement this. + """ + + def update(self, instance: models.Model, validated_data: dict) -> models.Model: + """Validate that no frozen fields were changed and update the instance.""" + for field_name in getattr(self.Meta, 'frozen_fields', ()): + if field_name in validated_data: + raise ValidationError( + { + field_name: ["This field cannot be updated."] + } + ) + return super().update(instance, validated_data) + class BotSettingSerializer(ModelSerializer): """A class providing (de-)serialization of `BotSetting` instances.""" @@ -426,7 +451,7 @@ class FilterListSerializer(ModelSerializer): # endregion -class InfractionSerializer(ModelSerializer): +class InfractionSerializer(FrozenFieldsMixin, ModelSerializer): """A class providing (de-)serialization of `Infraction` instances.""" class Meta: @@ -447,6 +472,7 @@ class InfractionSerializer(ModelSerializer): 'dm_sent', 'jump_url' ) + frozen_fields = ('id', 'inserted_at', 'type', 'user', 'actor', 'hidden') def validate(self, attrs: dict) -> dict: """Validate data constraints for the given data and abort if it is invalid.""" @@ -683,7 +709,7 @@ class NominationEntrySerializer(ModelSerializer): fields = ('nomination', 'actor', 'reason', 'inserted_at') -class NominationSerializer(ModelSerializer): +class NominationSerializer(FrozenFieldsMixin, ModelSerializer): """A class providing (de-)serialization of `Nomination` instances.""" entries = NominationEntrySerializer(many=True, read_only=True) @@ -703,9 +729,10 @@ class NominationSerializer(ModelSerializer): 'entries', 'thread_id' ) + frozen_fields = ('id', 'inserted_at', 'user', 'ended_at') -class OffensiveMessageSerializer(ModelSerializer): +class OffensiveMessageSerializer(FrozenFieldsMixin, ModelSerializer): """A class providing (de-)serialization of `OffensiveMessage` instances.""" class Meta: @@ -713,3 +740,4 @@ class OffensiveMessageSerializer(ModelSerializer): model = OffensiveMessage fields = ('id', 'channel_id', 'delete_date') + frozen_fields = ('id', 'channel_id') |