development

Django REST 프레임 워크에 사용자를 등록하는 방법은 무엇입니까?

big-blog 2020. 12. 27. 20:41
반응형

Django REST 프레임 워크에 사용자를 등록하는 방법은 무엇입니까?


Django REST 프레임 워크 로 REST API를 코딩하고 있습니다. API는 소셜 모바일 앱의 백엔드가 될 것입니다. 자습서를 수행 한 후 모든 모델을 직렬화 할 수 있으며 새 리소스를 만들고 업데이트 할 수 있습니다.

인증을 위해 AuthToken을 사용하고 있습니다.

내 질문은 :

/users리소스가 확보 되면 앱 사용자가 등록 할 수 있기를 바랍니다. 그렇다면 /register익명 사용자가 /users새 리소스 에 게시 할 수 있도록 별도의 리소스를 사용 하거나 허용 하는 것이 더 낫 습니까?

또한 권한에 대한 몇 가지 지침이 좋습니다.


serializer가 암호를 표시 / 검색 할 것으로 예상하지 않기 때문에 등록을 처리하기위한 고유 한 사용자 지정보기를 만들었습니다. URL을 / users 리소스와 다르게 만들었습니다.

내 URL 설정 :

url(r'^users/register', 'myapp.views.create_auth'),

내 견해 :

@api_view(['POST'])
def create_auth(request):
    serialized = UserSerializer(data=request.DATA)
    if serialized.is_valid():
        User.objects.create_user(
            serialized.init_data['email'],
            serialized.init_data['username'],
            serialized.init_data['password']
        )
        return Response(serialized.data, status=status.HTTP_201_CREATED)
    else:
        return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)

내가 틀렸을 수도 있지만 인증되지 않은 요청을 원하기 때문에이보기에 대한 권한을 제한 할 필요가없는 것 같습니다.


Django REST Framework 3 은 serializer에서 메서드 재정의를 허용합니다create .

from rest_framework import serializers
from django.contrib.auth import get_user_model # If used custom user model

UserModel = get_user_model()


class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(write_only=True)

    def create(self, validated_data):

        user = UserModel.objects.create(
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()

        return user

    class Meta:
        model = UserModel
        # Tuple of serialized model fields (see link [2])
        fields = ( "id", "username", "password", )

상속 된 클래스의 직렬화 된 필드는 Django Rest Framework v3.5 및 최신 버전 ModelSerializer에서 특허로 선언되어야합니다 .Meta

api.py 파일 :

from rest_framework import permissions
from rest_framework.generics import CreateAPIView
from django.contrib.auth import get_user_model # If used custom user model

from .serializers import UserSerializer


class CreateUserView(CreateAPIView):

    model = get_user_model()
    permission_classes = [
        permissions.AllowAny # Or anon users can't register
    ]
    serializer_class = UserSerializer

DRF 3.x에서 작동하는 가장 간단한 솔루션 :

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

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name']
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

다른 변경은 필요하지 않습니다. 인증되지 않은 사용자에게 새 사용자 개체를 만들 수있는 권한이 있는지 확인하기 만하면됩니다.

write_only_fields덮어 쓴 create방법은 암호가 일반 텍스트가 아닌 해시로 저장되도록하는 동안 암호 (실제로는 우리가 저장 한 해시)가 표시되지 않도록합니다.


Django 1.5의 사용자 지정 사용자 모델을 지원하기 위해 Cahlan의 답변을 업데이트하고 응답에 사용자의 ID를 반환했습니다.

from django.contrib.auth import get_user_model

from rest_framework import status, serializers
from rest_framework.decorators import api_view
from rest_framework.response import Response

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()

@api_view(['POST'])
def register(request):
    VALID_USER_FIELDS = [f.name for f in get_user_model()._meta.fields]
    DEFAULTS = {
        # you can define any defaults that you would like for the user, here
    }
    serialized = UserSerializer(data=request.DATA)
    if serialized.is_valid():
        user_data = {field: data for (field, data) in request.DATA.items() if field in VALID_USER_FIELDS}
        user_data.update(DEFAULTS)
        user = get_user_model().objects.create_user(
            **user_data
        )
        return Response(UserSerializer(instance=user).data, status=status.HTTP_201_CREATED)
    else:
        return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)

일반적으로 사용자보기는 권한이 필요한 다른 API 끝점과 동일하게 취급합니다. 단,보기 클래스의 권한 집합을 POST (만들기)에 대한 고유 한 권한 집합으로 재정의하기 만하면됩니다. 일반적으로이 패턴을 사용합니다.

from django.contrib.auth import get_user_model
from rest_framework import viewsets
from rest_framework.permissions import AllowAny


class UserViewSet(viewsets.ModelViewSet):
    queryset = get_user_model().objects
    serializer_class = UserSerializer

    def get_permissions(self):
        if self.request.method == 'POST':
            self.permission_classes = (AllowAny,)

        return super(UserViewSet, self).get_permissions()

좋은 측정을 위해 일반적으로 사용하는 직렬 변환기는 다음과 같습니다.

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = get_user_model()
        fields = (
            'id',
            'username',
            'password',
            'email',
            ...,
        )
        extra_kwargs = {
            'password': {'write_only': True},
        }

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

    def update(self, instance, validated_data):
        if 'password' in validated_data:
            password = validated_data.pop('password')
            instance.set_password(password)
        return super(UserSerializer, self).update(instance, validated_data)

djangorestframework 3.3.x / Django 1.8.x


위의 @cpury는 write_only_fields옵션 사용을 제안했습니다 . 그러나 이것은 DRF 3.3.3에서 나를 위해 작동하지 않았습니다.

DRF 3.0 에서는 write_only_fieldsModelSerializer 옵션이 PendingDeprecation으로 이동되었으며 DRF 3.2 에서는보다 일반적인 extra_kwargs로 대체되었습니다.

extra_kwargs = {'password': {'write_only': True}}


All of the answers so far create the user, then update the user's password. This results in an two DB writes. To avoid an extra unnecessary DB write, set the user's password before saving it:

from rest_framework.serializers import ModelSerializer

class UserSerializer(ModelSerializer):

    class Meta:
        model = User

    def create(self, validated_data):
        user = User(**validated_data)
        # Hash the user's password.
        user.set_password(validated_data['password'])
        user.save()
        return user

A little late to the party, but might help someone who do not want to write more lines of code.

We can user the super method to achieve this.

class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(
          write_only=True,
    )

    class Meta:
       model = User
       fields = ('password', 'username', 'first_name', 'last_name',)

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

A Python 3, Django 2 & Django REST Framework viewset based implementation:

File: serializers.py

from rest_framework.serializers import ModelSerializers
from django.contrib.auth import get_user_model

UserModel = get_user_model()

class UserSerializer(ModelSerializer):
    password = serializers.CharField(write_only=True)

    def create(self, validated_data):
        user = UserModel.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name'],
        )
        return user

    class Meta:
        model = UserModel
        fields = ('password', 'username', 'first_name', 'last_name',)

File views.py:

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin
from django.contrib.auth import get_user_model
from .serializers import UserSerializer

class CreateUserView(CreateModelMixin, GenericViewSet):
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer

File urls.py

from rest_framework.routers import DefaultRouter
from .views import CreateUserView

router = DefaultRouter()
router.register(r'createuser', CreateUserView)

urlpatterns = router.urls

ReferenceURL : https://stackoverflow.com/questions/16857450/how-to-register-users-in-django-rest-framework

반응형