diff options
author | 2020-08-26 21:59:46 +0530 | |
---|---|---|
committer | 2020-08-26 21:59:46 +0530 | |
commit | 8e636a54b449f44f5bff56577a05d9a6a2dd72c0 (patch) | |
tree | b69d8cab36ccf49281c47447839de7e2efe1245f /pydis_site/apps/api/serializers.py | |
parent | add pagination for GET request on /bot/users endpoint (diff) |
add support for bulk updates on user model
implemented a method to handle bulk updates on user model via a new endpoint: /bot/users/bulk_patch
Diffstat (limited to 'pydis_site/apps/api/serializers.py')
-rw-r--r-- | pydis_site/apps/api/serializers.py | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 52e0d972..757faeae 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -1,5 +1,13 @@ """Converters from Django models to data interchange formats and back.""" -from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError +from django.db.models.query import QuerySet +from rest_framework.serializers import ( + ListSerializer, + ModelSerializer, + PrimaryKeyRelatedField, + ValidationError +) +from rest_framework.settings import api_settings +from rest_framework.utils import html from rest_framework.validators import UniqueTogetherValidator from rest_framework_bulk import BulkSerializerMixin @@ -260,6 +268,72 @@ class TagSerializer(ModelSerializer): fields = ('title', 'embed') +class UserListSerializer(ListSerializer): + """List serializer for User model to handle bulk updates.""" + + def to_internal_value(self, data: list) -> list: + """ + Overriding `to_internal_value` function with a few changes to support bulk updates. + + List of dicts of native values <- List of dicts of primitive datatypes. + """ + if html.is_html_input(data): + data = html.parse_html_list(data, default=[]) + + if not isinstance(data, list): + message = self.error_messages['not_a_list'].format( + input_type=type(data).__name__ + ) + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='not_a_list') + + if not self.allow_empty and len(data) == 0: + message = self.error_messages['empty'] + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='empty') + + ret = [] + errors = [] + + for item in data: + # inserted code + # bug: https://github.com/miki725/django-rest-framework-bulk/issues/68 + # ----------------- + try: + self.child.instance = self.instance.get(id=item['id']) + except User.DoesNotExist: + self.child.instance = None + # ----------------- + self.child.initial_data = item + try: + validated = self.child.run_validation(item) + except ValidationError as exc: + errors.append(exc.detail) + else: + ret.append(validated) + errors.append({}) + + if any(errors): + raise ValidationError(errors) + + return ret + + def update(self, instance: QuerySet, validated_data: list) -> list: + """Override update method to support bulk updates.""" + instance_mapping = {user.id: user for user in instance} + data_mapping = {item['id']: item for item in validated_data} + + updated = [] + for book_id, data in data_mapping.items(): + book = instance_mapping.get(book_id, None) + if book is not None: + updated.append(self.child.update(book, data)) + + return updated + + class UserSerializer(BulkSerializerMixin, ModelSerializer): """A class providing (de-)serialization of `User` instances.""" @@ -269,6 +343,7 @@ class UserSerializer(BulkSerializerMixin, ModelSerializer): model = User fields = ('id', 'name', 'discriminator', 'roles', 'in_guild') depth = 1 + list_serializer_class = UserListSerializer class NominationSerializer(ModelSerializer): |