aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/apps/api/serializers.py
diff options
context:
space:
mode:
authorGravatar jchristgit <[email protected]>2023-12-11 18:09:39 +0100
committerGravatar GitHub <[email protected]>2023-12-11 17:09:39 +0000
commite8f8161e41a4735897b3038e202107f5d55ec96e (patch)
tree51998b09ecd506df7562f8eaa564c7154f4bdddc /pydis_site/apps/api/serializers.py
parentImplement 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.py34
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')