update tutorial serializermethodfield queryset modelserializer method framework español python django django-models django-rest-framework django-serializer

python - tutorial - partial update django rest framework



Amplíe el modelo de usuario Django REST framework 3.xx (2)

Así es como lo hice:

def update(self, instance, validated_data): # First, update the User user_data = validated_data.pop(''user'', None) for attr, value in user_data.items(): setattr(instance.user, attr, value) # Then, update UserProfile for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() return instance

Básicamente, investigué el código original para serializers ( aquí, línea 800 ) y lo modifiqué para que se ajustara a mis necesidades.

Buena suerte.

Estoy intentando ampliar el marco de reposo Django (versión 3.xx) con los campos gender , created_at , updated_at que están definidos en un modelo separado llamado UserProfile . Cuando intento actualizar la instancia del modelo UserProfile , incluida la instancia anidada del modelo de User , solo se actualiza la instancia UserProfile ( gender, updated_at fields ). Básicamente, lo que quiero lograr es poder actualizar también los campos de email, first_name and last_name del modelo de User

models.py:

class UserProfile(models.Model): user = models.OneToOneField(User, primary_key = True, related_name = ''profile'') gender = models.CharField(choices = GENDERS, default = 2, max_length = 64) created_at = models.DateTimeField(auto_now_add = True) updated_at = models.DateTimeField(auto_now = True) def __unicode__(self): return self.user.username @receiver(post_save, sender = User) def create_profile_for_user(sender, instance = None, created = False, **kwargs): if created: UserProfile.objects.get_or_create(user = instance) @receiver(pre_delete, sender = User) def delete_profile_for_user(sender, instance = None, **kwargs): if instance: user_profile = UserProfile.objects.get(user = instance) user_profile.delete()

serializers.py:

class UserProfileSerializer(serializers.ModelSerializer): id = serializers.IntegerField(source = ''pk'', read_only = True) username = serializers.CharField(source = ''user.username'', read_only = True) email = serializers.CharField(source = ''user.email'') first_name = serializers.CharField(source = ''user.first_name'') last_name = serializers.CharField(source = ''user.last_name'') class Meta: model = UserProfile fields = ( ''id'', ''username'', ''email'', ''first_name'', ''last_name'', ''created_at'', ''updated_at'', ''gender'', ) read_only_fields = (''created_at'', ''updated_at'',) def update(self, instance, validated_data): #user = User.objects.get(pk = instance.user.pk); user = instance.user user.email = validated_data.get(''user.email'', user.email) user.first_name = validated_data.get(''user.first_name'', user.first_name) user.last_name = validated_data.get(''user.last_name'', user.last_name) user.save() instance.gender = validated_data.get(''gender'', instance.gender) instance.save() return instance def create(self, validated_data): user_data = validated_data.pop(''user'') user = User.objects.create(**user_data) profile = UserProfile.objects.create(user = user, **validated_data) return profile

views.py:

class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer class UserProfileViewSet(viewsets.ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializer


Una ligera modificación al código anterior reemplazando el None con {}

Porque el objeto ''NoneType'' no tiene atributos ''items''

def update(self, instance, validated_data): # First, update the User user_data = validated_data.pop(''user'', {}) for attr, value in user_data.items(): setattr(instance.user, attr, value) # Then, update UserProfile for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() return instance

Hay otra manera que estoy implementando que se ocupa de la validación. Lo estoy implementando para manejar PATCH

class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = (''email'', ''first_name'', ''last_name'') class ProfileSerializer(serializers.ModelSerializer): email = serializers.CharField(source=''user.email'') first_name = serializers.CharField(source=''user.first_name'') last_name = serializers.CharField(source=''user.last_name'') class Meta: model = Profile exclude = (''user'',) def update(self, instance, validated_data): user_data = validated_data.pop(''user'', {}) user_serializer = UserSerializer(instance.user, data=user_data, partial=True) user_serializer.is_valid(raise_exception=True) user_serializer.update(instance.user, user_data) super(ProfileSerializer, self).update(instance, validated_data) return instance