본문 바로가기
내일배움캠프 AI 웹 프로그래밍

내일배움캠프 46일차 TIL_Django framework활용해서 custom user 만들기/ custom user 어드민 만들기 / 회원가입과 로그인을 위한 urls.py와 views.py

by thriveview 2023. 10. 6.

3-6. Custom user 만들고 등록하기

더 유동적으로 설계하기위해서 따로 Django framework 사이트 활용해서 custom user 만들기 

https://docs.djangoproject.com/en/4.1/topics/auth/customizing/

위사이트에서 custom users and proxy models> A full example
(⚫ 여기 설명부분은 추후 수정⚫여기서 abstractbaseuser 사용해서 처음부터 설정을 해주는 방법 사용
유저네임필드  = 이메일, 닉네임도 가능하게 
장고에서는 모든 매니저 클래스가 헬퍼 클래스라고 기본적으로 작동하는것이며 추가적으로 메소드들이 정의가 되어 있고 직접적으로 데이터베이스와 데이터를 주고받는것들이 매니저 클래스에 저장되어있다 

#순서
custom users and proxy models> A full example> #전부 복사
#users>models.py 에 붙여넣기 
#수정하기, MyUsermanager 이름은 My삭제 (전부다)



다시 사이트와서( https://docs.djangoproject.com/en/4.1/topics/auth/customizing/ )
Substituting a custom User model에서 Auth 설치할 부분 copy. drt_project>setting.py>맨아래 추가 (my 제외) / myapp 이름도 내가 지정한 app 이름으로 수정


지금까지 만든 db.sqlite는 삭제하자. 중간에 커스텀 유저로 바뀌는건 쉽지않음 처음부터 커스텀 유저를 설정해주고 하는게 데이터베이스를 살리는길

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

 

#users>models.py 에서 생년월일 모두 삭제 

python manage.py makemigrations
python manage.py migrate #model.py에 변경을 주었기때문에 다시 migrate

#db.sqlite3 폴더들어가서 users_user 에서 생년월일 빠졌는지 확인

#모델을 만들었으니 테스트를 해보자 (admin page 등록)
#users > admin.py 

from django.contrib import admin 
from .models import User

admin.site.register(User)

#위와 같이 수정후, creatsuperuser

python manage.py createsuperuser

#이메일 등록후, 페이지 확인

 

그런데 페이지를 보면 비밀번호가 hashing이 되지않고 저장이되는 사태가 발생한다. 

 

 

 

파이썬 장고 실무 심화 3.7 custom user 어드민 만들기 

지난시간과 마찬가지로 아래 사이트에서 등록할 코드 확인하기

https://docs.djangoproject.com/en/4.1/topics/auth/customizing/
 
users>admin.py에 복붙하기
언제나~~ framework 활용할땐 내가 진행하는 프로젝트 폴더/파일명으로 수정해주고 사용하지않는 기능은 제외하며 수정해주기 

from users.models import User #이렇게 변경. MyUser은 전부 User로 변경
#필요없는 사항 삭제 및 수정하고 확인 
#error가 뜬다면 재확인
#users>admin.py에 수정완료한 코드

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from users.models import User


class UserCreationForm(forms.ModelForm):
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

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

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = ('email', 'password', 'is_active', 'is_admin')


class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2'),
        }),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()


# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)

 

이렇게 완료하고나서 사이트에서 refresh해보면 hashing이 된 것을 확인할 수 있다. 

이유가 무엇일까? 

 from django.contrib.auth.forms import ReadOnlyPasswordHashField 

이 부분에서 ReadOnlyPasswordHashField 때문이다. 읽기만 가능하며 패스워드는 해싱해주는 고마운 친구.

 

파이썬 장고 실무 심화 3-8. 회원가입과 로그인을 위한 urls.py와 views.py 


API를 사용하여 회원가입과 로그인 할 수 있는지 보자. 
회원가입을 위한 API만들기 

#users>urls.py

from django.urls import path, include
from users import views
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('signup/', views.UserView.as_view(), name='user_view' ),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

 

#urls.py 완료했다면 users>views.py 

from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response

from users.serializers import Userserializer #import하기

class UserView(APIView):
    def post(self, request):
        serializer = Userserializer(data=request.data) #serializers.py 만들어주기
        if serializer.is_valid():
            serializer.save()
            return Response({"message":"가입완료!"}, status=status.HTTP_201_CREATED)
        else:
            return Response({"message":f"${serializer.errors}"}, status=status.HTTP_400_BAD_REQUEST)
#serializers.py 파일 만들어주고 코드 아래와 같이

from rest_framework import serializers
from users.models import User


class Userserializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields= "__all__"

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

 

완료된 postman