본문 바로가기

코딩/장고

django login knox (user extention one to one)

settings.py

from datetime import timedelta

INSTALLED_APPS = [
	...
    'knox',
]

REST_KNOX = {
  'SECURE_HASH_ALGORITHM': 'cryptography.hazmat.primitives.hashes.SHA512',
  'AUTH_TOKEN_CHARACTER_LENGTH': 64,
  'TOKEN_TTL': timedelta(hours=10),
  'USER_SERIALIZER': 'knox.serializers.UserSerializer',
  'TOKEN_LIMIT_PER_USER': None,
  'AUTO_REFRESH': False,
}

REST_FRAMEWORK = {
    # 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    # 'PAGE_SIZE': 10,
    'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',),
}

 

 

users/views.py

from .serializers import *
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from knox.models import AuthToken
from knox.views import LoginView as KnoxLoginView
from rest_framework.authtoken.serializers import AuthTokenSerializer
from django.contrib.auth import login


# 회원가입
class RegistrationAPI(generics.GenericAPIView):
    serializer_class = CreateUserSerializer

    def post(self, request, *args, **kwargs):
        if len(request.data["username"]) < 6 or len(request.data["password"]) < 4:
            body = {"message": "short field"}
            return Response(body, status=status.HTTP_400_BAD_REQUEST)

        print("request.data : ", request.data["profile"])
        print("request.data : ", request.data["profile"]["email"])

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        print('3')
        user = serializer.save()
        print('4')
        # profile을 instance로 넘기는 방법을 몰라서
        # view에서 save로 강제로 저장
        print('user :: ', user)
        profile = Profile(user=user, user_pk=user.id, email=request.data["profile"]["email"])
        profile.save()

        return Response(
            {
                "user": UserSerializer(
                    user, context=self.get_serializer_context()
                ).data,
                "token": AuthToken.objects.create(user)[1],
            }
        )


class LoginView(KnoxLoginView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        serializer = AuthTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginView, self).post(request, format=None)


class UserAPI(generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user


class LoginAPI(generics.GenericAPIView):
    serializer_class = LoginUserSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        user = serializer.validated_data
        user_serializer = UserSerializer(user, context=self.get_serializer_context()).data

        return Response(
            {
                "user": user_serializer,
                "token": AuthToken.objects.create(user)[1],
            }
        )


class ProfileUpdateAPI(generics.UpdateAPIView):
    lookup_field = "user_pk"
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

 

 

 

urls.py

from django.conf.urls import url
from .views import *
from . import views
from django.urls import path, include
from django.contrib import admin
from knox import views as knox_views


urlpatterns = [
    path('auth/register/', RegistrationAPI.as_view()),
    path('auth/user/', UserAPI.as_view()), 
    path("auth/profile/<int:user_pk>/update/", ProfileUpdateAPI.as_view()),
    
    # 원본
    url(r'login/', LoginView.as_view(), name='knox_login'),
    # 커스텀
    path('auth/login/', LoginAPI.as_view()),
]

 

from django.urls import path
from . import views
from users.views import *
from django.conf.urls import url
from django.urls import path, include, re_path

app_name="users"

urlpatterns = [
    url(r'login/', LoginView.as_view(), name='knox_login'),
    path('auth/user/', UserAPI.as_view()),
    url(r"auth/", include("knox.urls")),
]

 

 

models.py

from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    user_pk = models.IntegerField(blank=True)
    email = models.EmailField(max_length=500, blank=True)
    nickname = models.CharField(max_length=200, blank=True)
    point = models.IntegerField(default=0)
    like = models.CharField(max_length=200, blank=True)
    phone = models.CharField(max_length=200, blank=True)

 

 

from rest_framework import serializers

from django.contrib.auth.models import User
from django.contrib.auth import authenticate

# 접속 유지중인지 확인할 시리얼라이저

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("id", "username", "first_name")

class CreateUserSerializer(serializers.ModelSerializer):
    # profile = AddProfileSerializer()
    class Meta:
        model = User
        fields = ("id", "username", "password", "email")
        extra_kwargs = {"password": {"write_only": True}}

    def create(self, validated_data):
        user = User.objects.create_user(
          validated_data["username"]
            , validated_data["email"]
            , validated_data["password"]
        )
        return user

# 로그인 시리얼라이저

class LoginUserSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, data):
        user = authenticate(**data)
        if user and user.is_active:
            return user
        raise serializers.ValidationError("Unable to log in with provided credentials.")


class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ("user_pk", "nickname", "phone", "email")

 


회원 등록 postman

 

로그인

 

로그인 확인(세션)

 

유저 정보 수정 postman

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

devlog.jwgo.kr/2019/11/06/what-is-django-rest-knox/

 

django-rest-knox 란 무엇이고 왜 필요한가요. · Tonic

사이트 운영에 도움을 주실 수 있습니다. 고맙습니다. --> django-rest-knox 란 무엇이고 왜 필요한가요. 2019년 11월 06일 django-rest-knox는 장고(django)의 rest 인증 모듈입니다. Knox는 Django REST Framework의 인

devlog.jwgo.kr

 

velog.io/@killi8n/Dnote-5-1.-Django-%EA%B6%8C%ED%95%9C-%EC%84%A4%EC%A0%95-%EB%B0%8F-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EA%B5%AC%ED%98%84-tmjmep5tcm