6

próbuję przedłużyć odpoczynek Django Framework (wersja 3.x.x) z gender, created_at, updated_at dziedzinach, które są zdefiniowane w osobnym modelem o nazwie UserProfile. Podczas próby zaktualizowania instancji modelu UserProfile włącznie z instancją modelu zagnieżdżonego User aktualizowana jest tylko instancja UserProfile (gender, updated_at fields). Więc w zasadzie to, co chcę osiągnąć to, aby móc zaktualizować również pola email, first_name and last_name z modelu UserRozszerzanie modelu użytkownika Django REST ramy 3.x.x

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 

Odpowiedz

4

Oto jak to zrobiłem:

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 

Zasadniczo, zajrzałem do oryginalnego kodu dla serializers (here, line 800) i zmodyfikowany tak, że będzie pasować do moich potrzeb.

Powodzenia.

+0

tam jest błąd, ponieważ to daje mi, że 'użytkownik portu nie jest określony, może być to znaczy' instance.user = user_data' – L3K0V

+0

Faktycznie, że linia nie jest nawet konieczne, ponieważ wszystkie atrybuty są ustawione bezpośrednio na instancji użytkownika. Usuń go i powinno działać dobrze :) – AdelaN

1

Nieznaczne zmiany w powyższym kodzie zastępującego Żaden z {}

Ponieważ obiekt „NoneType” nie ma atrybutu „przedmioty”

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 

Jest też inny sposób, że jestem wykonawcze, które zajmuje zatwierdzenia. Ja jej wdrażania do obsługi 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