From 7d3d7104d935f740a5d820003dffd076464bed01 Mon Sep 17 00:00:00 2001 From: Dustin Pianalto Date: Sat, 14 Dec 2019 02:45:15 -0900 Subject: [PATCH] Modify user serializer update to have expected behavior Updates should add to many to many relationships not set them. --- geeksbot_web/users/serializers.py | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/geeksbot_web/users/serializers.py b/geeksbot_web/users/serializers.py index 73dac33..b2b1d16 100644 --- a/geeksbot_web/users/serializers.py +++ b/geeksbot_web/users/serializers.py @@ -1,4 +1,6 @@ from rest_framework import serializers +from rest_framework.serializers import raise_errors_on_nested_writes +from rest_framework.utils import model_meta from users.models import User from users.models import UserLog @@ -45,7 +47,37 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): prev_discrims = set(instance.previous_discriminators or []) prev_discrims.add(instance.discriminator) validated_data['previous_discriminators'] = list(prev_discrims) - return super(UserSerializer, self).update(instance, validated_data) + if 'guild' in validated_data and 'guilds' not in validated_data: + validated_data['guilds'] = [validated_data['guild']] + + # Copied with slight changes from super.update() + raise_errors_on_nested_writes('update', self, validated_data) + info = model_meta.get_field_info(instance) + + # Simply set each attribute on the instance, and then save it. + # Note that unlike `.create()` we don't need to treat many-to-many + # relationships as being a special case. During updates we already + # have an instance pk for the relationships to be associated with. + m2m_fields = [] + for attr, value in validated_data.items(): + if attr in info.relations and info.relations[attr].to_many: + m2m_fields.append((attr, value)) + else: + setattr(instance, attr, value) + + instance.save() + + # Note that many-to-many fields are set after updating instance. + # Setting m2m fields triggers signals which could potentially change + # updated instance and we do not want it to collide with .update() + for attr, value in m2m_fields: + field = getattr(instance, attr) + if isinstance(value, (list, tuple, set)): + field.add(*value) + else: + field.add(value) + + return instance class UserLogSerializer(serializers.ModelSerializer):