장고(Django) 사용자 인증 테스트 하면서 제대로 이해 못해서 삽질하다 기능 구현에 성공했다.
RSA 암호화/복호화 처리하는 코드는 배제하고 URL Redirection 처리 구현 목적으로 테스트했다.
장고에서 기본 제공하는 Custom User Model은 https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example 을 참고하면 된다.
로그인이 안되어 있으면 로그인 화면으로 이동하도록 하는 옵션을 설정한다.
login_url 과 redirect_field_name 을 추가 해준다.
#--- ListView
class PostLV(LoginRequiredMixin,ListView):
model = Post
template_name = 'blog/post_all.html'
context_object_name = 'posts'
paginate_by = 2
login_url = '/login/'
redirect_field_name = 'redirect_to'
|
Mixin 클래스 : 자신의 인스턴스를 만드는 용도보다는 다른 클래스에게 부가 기능을 제공하기 위한 용도로 사용되는 클래스를 의미한다.
forms.py
class UserLoginForm(forms.Form):
username = forms.CharField(
max_length=32, label='userID',
widget=forms.TextInput(
attrs={
"placeholder": "Username",
"class": "form-control"
}
))
password = forms.CharField(
label='비밀번호',
widget=forms.PasswordInput(
attrs={
"placeholder": "Password",
"class": "form-control"
}
))
def clean(self):
if self.is_valid():
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if not authenticate(username=username, password=password):
raise forms.ValidationError("입력 정보를 확인하세요.")
|
https://swarf00.github.io/2018/12/10/login.html 를 자세히 읽어보지 않고
대충 복사/붙여넣기 했더니 원하는데로 동작되지 않는다.
# accounts/views.py
from django.conf import settings
from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME
from django.contrib.auth.views import SuccessURLAllowedHostsMixin
from django.contrib.sites.shortcuts import get_current_site
from is_safe_url import is_safe_url
from django.urls import reverse_lazy, reverse
from django.views.decorators.cache import never_cache
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, FormView
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.shortcuts import render, redirect, resolve_url
from .forms import SignUpForm, LoginForm, UserLoginForm
from .RSACipher import *
from .models import User
# from django.contrib.auth.models import User
class UserLoginView(SuccessURLAllowedHostsMixin,FormView):
template_name = 'accounts/userlogin.html'
form_class = UserLoginForm
redirect_field_name = REDIRECT_FIELD_NAME
redirect_authenticated_user = False
authentication_form = None
extra_context = None
# success_url = reverse_lazy("home")
@method_decorator(sensitive_post_parameters())
@method_decorator(csrf_protect)
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
if self.redirect_authenticated_user and self.request.user.is_authenticated:
redirect_to = self.get_success_url()
if redirect_to == self.request.path:
raise ValueError(
"Redirection loop for authenticated user detected. Check that "
"your LOGIN_REDIRECT_URL doesn't point to a login page."
)
return HttpResponseRedirect(redirect_to)
return super().dispatch(request, *args, **kwargs)
def get_success_url(self):
url = self.get_redirect_url()
print("get_success_url : {}".format(url))
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
def get_redirect_url(self):
redirect_to = self.request.POST.get(
self.redirect_field_name, # 1. 폼의 필드 중 next 이름을 가진 필드 값
self.request.GET.get(self.redirect_field_name, '')
# 2. query parameter 중 next 이름을 가진 값
)
url_is_safe = is_safe_url(
url=redirect_to,
allowed_hosts=self.get_success_url_allowed_hosts(),
require_https=self.request.is_secure(),
)
return redirect_to if url_is_safe else ''
def form_valid(self, form):
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(self.request, username=username, password=password)
if user is not None and user.is_active:
login(self.request,user)
return super().form_valid(form)
|
로그인하면 Home 화면으로 무조건 이동하는 것은 아래와 같이 구현하면 된다.
# accounts/views.py
from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME
from django.contrib.auth.views import SuccessURLAllowedHostsMixin
from django.urls import reverse_lazy, reverse
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, FormView
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect, resolve_url
from .forms import SignUpForm, LoginForm, UserLoginForm
from .RSACipher import *
from .models import User
# from django.contrib.auth.models import User
class UserLoginView(SuccessURLAllowedHostsMixin,FormView):
template_name = 'accounts/userlogin.html'
form_class = UserLoginForm
success_url = reverse_lazy("home")
def form_valid(self, form):
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(self.request, username=username, password=password)
if user is not None and user.is_active:
login(self.request,user)
return super().form_valid(form)
|
게시글 List를 클릭할 때 인증되어 있지 않으면 인증 URL 로 이동하고, 인증 완료후 원래 게시글 List 화면으로 이동하는 기능을 구현하려고 엄청 삽질을 좀 했다.
세션 처리를 하면 금방 해결될 사항이었는데 말이다.
# accounts/views.py
from django.conf import settings
from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME
from django.urls import reverse_lazy, reverse
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, FormView
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect, resolve_url
from .forms import SignUpForm, LoginForm, UserLoginForm
from .models import User
# from django.contrib.auth.models import User
class UserLoginView(FormView):
template_name = 'accounts/userlogin.html'
form_class = UserLoginForm
# success_url = reverse_lazy("home")
def form_valid(self, form):
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(self.request, username=username, password=password)
if user is not None and user.is_active:
login(self.request,user)
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.GET.get("redirect_to"):
redirect_to = self.request.GET.get("redirect_to")
self.request.session['redirect_to'] = redirect_to
return context
def get_success_url(self):
url = self.request.session.get('redirect_to')
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
|
ㅇ View : 모든 클래스형 뷰의 기본이 되는 최상위 뷰. 모든 클래스형 뷰는 이 View 클래스를 상속받는다.
ㅇ TemplateView : 단순하게 화면에 보여줄 템플릿 파일을 처리하는 정도의 간단한 뷰
ㅇ FormView : 폼을 보여주기 위한 뷰. form_class, template_name, success_url 속성 필요하다.
만약 검색 결과를 같은 페이지에서 보여주고자 한다면, success_url 속성 지정은 생략한다.
form_class 는 FormView, CreateView, UpdateView 에서 사용한다.
ㅇ CreateView : 새로운 레코드를 생성해서 테이블에 저장해주는 뷰. FormView의 기능을 포함하고 있다.
폼을 만들 때 사용할 필드를 fields 속성으로 정의한다.
fields 는 CreateView, UpdateView 에서 사용한다.
ㅇ get_context_data(**kwargs) : 모든 제네릭 뷰에서 사용하는 메소드이다.
템플릿에서 사용할 context 데이터를 반환한다.
뷰에서 템플릿 파일에 넘겨주는 context 데이터를 추가하거나 변경할 수 있다.
ㅇ 모델 폼(ModelForm) : 모델에 정의한 필드를 참조해서 모델 폼을 만드는 역할을 한다.
'파이썬 > Django' 카테고리의 다른 글
Django REST Framework 입문 (0) | 2022.03.06 |
---|---|
Javascript RSA 암호화 및 Django RSA 복호화 (0) | 2022.02.02 |
Django default Form-based Login, Register (0) | 2022.01.31 |
Django Custom User Model - 회원가입, 로그인 (2) | 2022.01.29 |
Django, squash migrations (0) | 2022.01.26 |