2014-12-18 13 views
5

serializer:Django reszta ramy zagnieżdżone serializer częściowa zmiana

class ProfileSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = UserProfile 
     fields = ('foo', 'bar') 


class UserSerializer(serializers.ModelSerializer): 
    userprofile = ProfileSerializer(partial=True) 

    class Meta: 
     model = User 
     fields = ('username', 'password', 'email', 'userprofile') 

    def create(self, validated_data): 
     profile_data = validated_data.pop('userprofile') 
     user = User.objects.create(**validated_data) 
     UserProfile.objects.create(user=user, **profile_data) 

     return user 

    def update(self, instance, validated_data): 
     profile_data = validated_data.pop('userprofile') 
     profile = instance.userprofile 

     instance.username = validated_data.get('username', instance.username) 
     instance.email = validated_data.get('email', instance.email) 
     instance.save() 

     profile.foo = profile_data.get('foo', profile.foo) 
     profile.bar = profile_data.get('bar', profile.bar) 
     profile.save() 

     return instance 

Widok:

class UsersViewSet(viewsets.ModelViewSet): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    authentication_classes = (TokenAuthentication,) 
    permission_classes = (IsAuthenticated,) 

Zarówno tworzenie i aktualizacja pracują dobrze, problem jest z częściowych aktualizacji. Model użytkownika django ma wymaganą nazwę użytkownika i chciałbym, aby było to opcjonalne. Czy jest jakiś sposób, aby włączyć częściowe aktualizacje dla tego scenariusza?

Na przykład chciałbym zaktualizować z PUT tylko "foo".

Odpowiedz

5

Domyślnie PUT dostarczyć wszystkie wymagane argumenty. Ale PATCH nie jest. Tak długo, jak jesteś w stanie używać PATCH zamiast PUT, nie musisz w ogóle zmieniać swojego kodu.

Osobiście uważam, że to trochę dziwne, jak to działa, PUT wymaga wszystkich argumentów, które nie są opcjonalne, ale pozostawia opcjonalne argumenty w spokoju. Możesz więc edytować opcjonalne argumenty pozostawiając inne opcjonalne argumenty samodzielnie, ale nie możesz zrobić tego samego z wymaganymi argumentami (chodzi mi o to, że oczywiście możesz podać tylko istniejące wartości, ale jeśli zmieniły się podczas edycji, są wkręcone i wymuszą zmianę ich plecy). PATCH ma dla mnie dużo więcej sensu. Wszelkie argumenty, które dostarczysz, zostaną zmienione, a wszystkie, których nie otrzymasz, nie zostaną zmienione. IMO PUT powinno usunąć wszystkie opcjonalne argumenty, które nie są dostarczane, więc jest prawdziwym zamiennikiem, a nie tylko opcjonalnym zamiennikiem i aktualizacją (PUT).

4

skończyło się nadrzędnymi get_serializer wewnątrz UsersViewSet:

def get_serializer(self, instance=None, data=None, many=False, partial=False): 
     """If request is not PUT, allow partial updates.""" 
     if self.request.method == 'PUT': 
      return UserSerializer(instance=instance, data=data, many=many, partial=True) 
     else: 
      return UserSerializer(instance=instance, data=data, many=many, partial=partial) 

Zmuszanie częściowy True jeśli request.method kładzie. Nie jestem pewien, czy to jest najbardziej eleganckie rozwiązanie, ale działa. Jeśli ktoś ma lepsze rozwiązanie proszę zrobienia akcji :)

1

Faktycznie, następujący kod wspiera już częściową aktualizację:

instance.username = validated_data.get('username', instance.username) 

Ta funkcja „dostać” dostanie „login”pole od validated_data. Jeśli nie istnieje, zostanie zwrócona nazwa pliku instance.username. Oczekuje się

1

Użytkownik seriliazer musi zmienić coś jak

username = fields.CharField(required=False) 
Powiązane problemy