2015-04-20 3 views
5

Korzystanie django-rest-ramowej 3 i django 1,8Django ramy reszta utworzyć użytkownika z hasłem

Próbuję utworzyć użytkownika przy użyciu django-rest-ramową ModelViewSerializer. Problem polega na tym, że domyślna metoda objects.create używana przez DRF pozostawia hasło jako zwykły tekst.

Problem polega na tym, że metoda tworzenia serialera DRF używa metody objects.createquerysets/#create zamiast metody objects.create_user.

kod z serializers.py linia 775

instance = ModelClass.objects.create(**validated_data) 

Co jest najlepszym rozwiązaniem dla tego? Mogę przesłonić metodę serializer.create, aby użyć obiektu objects.user_create zamiast objects.create, ale nie jest to właściwe rozwiązanie.

reszta kodu:

from django.contrib.auth.models import User 
from rest_framework import viewsets 

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('username', 'email','password') 
     write_only_fields = ('password',) 


class UserViewSet(viewsets.ModelViewSet): 
    queryset = User.objects.all() 
    serializer = UserSerializer() 
+3

Dlaczego nie wydaje się prawo do ciebie? Myślę, że pójdę tą drogą. Wyszukałem trochę i przynajmniej znalazłem ten wpis SO (inne pytanie), ale nadpisanie 'create()' jest używane do tego celu w zaakceptowanej odpowiedzi. http: // stackoverflow.com/a/27763502/870769 – sthzg

Odpowiedz

8

można zastąpić create w UserSerilizer:

class UserSerializer(serializers.ModelSerializer): 
    # .... 

    def create(self, validated_data): 
     user = User.objects.create_user(**validated_data) 
     return user 

inne rozwiązania mogą być nadrzędne perform_create w klasie ViewSet lub można napisać swoją własną metodę create w swojej klasie viewset

class UserViewSet(viewsets.ModelViewSet): 
    def create(self, request, format=None): 
     # create user here 
     # do not call seriailzer.save() 

UPDATE: po @freethebees skomentował nadrzędnymi perform_create też działa, więc tutaj jest fragment kodu:

class UserViewSet(viewsets.ModelViewSet, mixins.CreateModelMixin): 
    def perform_create(self, serializer): 
     # use User.objects.create_user to create user 
     pass 

UWAGA: ta odpowiedź daje 3 rozwiązania, wybierz jedną uważasz, że lepiej pasuje do Twoich potrzeb i projekt ekosystemu

UWAGA 2 ja osobiście wolę nadrzędnymi create w UserViewSet (kod drugim fragmencie), ponieważ nie można po prostu przywrócić zwyczaj Response (na przykład zwróć profil użytkownika po zalogowaniu)

+0

Dlaczego polecasz przesłonięcie metody 'create' w serializatorze zamiast' perform_create' w ViewSet? – freethebees

+0

@freethebees to stara odpowiedź, nie pamiętam dlaczego :-), ale masz rację 'perform_create' wydaje się być czystszym rozwiązaniem, zaktualizuję odpowiedź. – aliva

+0

Och, nie sugerowałem, że tak czy inaczej było lepiej. Byłem po prostu zainteresowany. Nie widziałem, która metoda byłaby jasnym wyborem. – freethebees

1

Oprócz odpowiedzi @ aliva, gdzie brakuje Ci funkcji w serializers.Modelserializer.create() (co może być całkiem miłe dla zachowania, na przykład obsługa relacji wiele do wielu), jest sposób, aby to zatrzymać.

Stosując metodę user.set_password(), hasło może być również ustawiony prawidłowo, jak:

class UserSerializer(serializers.ModelSerializer): 

    def create(self, validated_data): 
     user = super().create(validated_data) 
     user.set_password(validated_data['password'] 
     user.save() 
     return user 

Ma to tę zaletę, utrzymując super klasy funkcjonalność, ale minusem dodatkowego zapisu w bazie danych. Zdecyduj, który kompromis jest dla Ciebie ważniejszy :-).

1

Jest nawet lepszym rozwiązaniem, aby potwierdzić hasło serializatora

from django.contrib.auth.hashers import make_password 

class UserSerializer(serializers.ModelSerializer): 
    def validate_password(self, value: str) -> str: 
     return make_password(value)