728x90

참고:

[Web Applicateion]서버 사이드와 클라이언트 사이드,백앤드와 프론트앤드


pip install django로 반드시 장고를 설치하여야한다.

또한 장고의 버전은 2이므로 1을 사용하는 사람들의 경우 서로 많이 차이날 수 있다는 점을 잘 알고 접근하여야 한다.


이제 슬슬 로그인을 구현하도록 해보자.

로그인 기능을 구현해본 사람들이 많을 것이다.

따라서 지금까지 배운걸 바탕으로 해보면 로그인을 구현하는건 실상 그리 어렵지 않다.

보통 로그인을 구현하기 위해서 필요한건 무엇인가?

가장 기본적인건 회원정보에 대한 모델(db 릴레이션)이 존재해야한다.

이름은 person,member,user등 다양한 이름으로 불리운다.

그러면 로그인 하는 form(html상의 폼 맞다)이 존재해야한다.

그러면 그 form은 특정 html 소스가 필요할 것이다.

그 다음은 인증의 구현이다. 인증의 방법역시 여러가지가 있다.

db를 사용하는 방법부터 cookie,session,server side script까지 다양한 방법으로 구현하게 된다.

보통은 session을 사용해서 구현하는게 일반적이다. 다른 방법은 각각의 한계를 지니기 때문.

즉 필요한걸 나열해보자.


user model : db relation

login form : form

login html : html

login url : url

login auth : 인증


최소한의 단위는 위와 같을 것이다.

어짜피 다른 웹프로그래밍 경력이 있다면 이를 구현하는건 어렵지 않고 시간이 오래 걸리지 않는다.

그러나 django는 훨씬 더 획기적이고 짧은 방법으로 구현할 수 있게 되어 있다.

왜냐하면 이미 위와 같은 것들이 구비되어 있어서 몇가지만 짧게 해주면 되기 때문이다.

그러면 한번 따라하여보자.


# urls.py
from django.contrib.auth import views as auth_views
from django.urls import path

urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
]

먼저 urls.py에 login url을 선택해야한다.

url의 이름을 뭐로하던 크게 상관없으나 보통의 경우 login으로 하는게 바람직 할것이다.


보면 알다시피 auth의 views를 import해준다. 이름이 겹칠 확률이 높으므로 auth_views로 앨리어싱(이름 짓기)을 해주자.

LoginView는 Class based view이므로 등록할때 as_view를 사용한다. 설명은 Django 9장 class based view를 참조하라.

이제 실행해보자.



그러면 registration/login.html이 없다고 우리에게 난리친다.

그렇다. LoginView는 가만냅두면 기본적으로 registration/login.html을 렌더링하게 되어있다.

우리는 아무리 간단한 LoginView도 registration/login.html을 사용해야한다는 것을 알 수 있다.

따라서 만들어 주자.


{#login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit">
<input type="reset" value="reset">
</form>
</body>
</html>

이 login.html은 반드시 templates폴더안에 login.html파일 안에 둔다.

이제 준비는 끝났다.

장고를 실행하고 페이지를 렌더링해 보아라.



우리는 form을 만들지도 않았는데 form이 렌더링 되어 있다.

이 폼의 경우에이미 정의되어 있기 때문이다.

그럼 여기서 사용하는 form으로 로그인할 수 있을까?

당연하다! 로그인할 수 있다. 그럼 여기서 사용하는 모델은 뭘까?



우리가 기본 로그인하는 Users모델을 그대로 사용한다.

즉 우리가 createsuperuser로 사용했던 Users모델로 로그인한다는 이야기이다.

이때 사용한 아이디와 패스워드로 로그인 해보자.



그러면 자동으로 accounts/profile로 리다이렉트된다.

이 url로 리다이렉트가 됬다면 로그인에 성공한 것이다.

로그인에 실패했다면 로그인이 되지 않았다고 뜬다. 뭔말인지 모르겠으면 강제로 한번 틀려봐라.

이 url은 로그인에 성공했을시 이 경로로 가게 되어있다는 뜻이다.

accounts/profile은 이름에서 유추할 수 있듯 개인이 로그인에 성공했을때 자동으로 가지는 url이다.

그러나 우리는 아직 이 부분을 신경쓰지 말자.

로그인에 성공했을때 자동으로 가는 url을 바꾸려면 settings.py를 변경하라.


# settings.py
LOGIN_REDIRECT_URL = '/'

settings.py의 어디에서든 LOGIN_REDIRECT_URL을 추가해주어라.

이 경로에 로그인에 성공했을 경우 가야할 URL을 선택할 수 있다.

이제 우리는 로그인에 성공했을 경우 root페이지에 가도록 선언되었다.

물론 해당 URL이 존재해야한다. 없으면 만들어 주어라. 물론 다른 페이지로 연결되도 상관은 없다.


이까지면 여러분은 로그인과 관련된 모든 기능을 만든 것이다.

??????

정말 만든거라고???

그렇다 정말 만들었다.

물론 당황할 마음 이해한다.

아직 아무것도 한게 없는거 같은데 만들었다는게 신기하기만 할 것이다.


그럼 로그인이 됬는지 한번 확인해보자.

여러분은 로그인을 왜하는가? 아마도 로그인해야만 이용할 수 있는 기능들을 사용하기위해서 로그인을 할것이다.

그럼 새로운 view를 만들어보자.


# views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.shortcuts import render


# Create your views here.
class IndexView(View):
def get(self, request, *args, **kwargs):
context = {'parm1': 'hello', 'parm2': 'django', 'auth': request.user.is_authenticated}
print(request.user)
return render(request, 'index.html', context=context)


def profile(request):
if not request.user.is_authenticated:
data = {'username': request.user, 'is_authenticated': request.user.is_authenticated}
else:
data = {'last_login': request.user.last_login, 'username': request.user.username,
'password': request.user.password, 'is_authenticated': request.user.is_authenticated}
return render(request, 'profile.html', context={'data': data})

profile이라는 view를 추가했다. 일단은 class based가 아닌 function based로 만들었다.

로그인을 했다면 아래를 안했다면 위를 반환한다. 두 캐이스를 다르게 한 이유는 로그인을 했을때의 값과 아닌값이 다르기 때문이다.

전달 하는데이터는 마지막 로그인 시간, 그리고 유저의 아이디(username). 패스워드와 로그인했는지의 여부이다.

여기서 request.user와 request.user.username은 로그인을 했다면 둘은 동등한 값을 반환한다.

단 로그인하지 않았다면 request.user.username은 없는 속성이 되므로 에러가 된다. 대신 request.user는 anonymouse user가 반환된다.


{#profile.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Profile</title>
</head>
<body>
{{ data.is_authenticated }}
<ul>
{% for key,value in data.items %}
{{ key }} : {{ value }}<br>
{% endfor %}
</ul>
</body>
</html>

이 profile.html의 예제는 값을 어떻게 써야하는지를 볼 수 있다.

딕셔너리의 items는 key와 value를 따로 빼내어 출력해준다.

그 값을 key와 value로 받자. 반복문을 써서 출력하려면 아래를,

반복문을 쓰지 않고 하나씩 불러내는것 역시 가능하다.

넘겨져온 값도 dictionary라고 생각하면 사용하는건 어렵지않다.



로그인을 하지 않았을 경우의 모습이다. is_authenticated는 False로 반환되어 로그인되지 않았음을 알 수있다.

그럼 이번엔 로그인을 해보라.


# settings.py
LOGIN_REDIRECT_URL = '/profile'

로그인하기전에 로그인 끝난후의 url을 profile로해보자.

그럼 편리하게 접근할 수 있을 것이다.



보다시피 로그인을 성공적으로 수행했음을 알 수있다.

이제 여러분은 로그인을 했을때와 로그인을 하지 않았을 때를 구별해서 코딩하는것 역시 가능하다는것을 알 수 있을 것이다.

로그인을 테스트하기 위해서 로그인을 했으니 로그아웃역시 만들어보자.

로그아웃을 만드는건 로그인보다 쉽다.


# urls.py
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path
from DjangoApp.views import IndexView, profile

urlpatterns = [
path('', IndexView.as_view(), name='index'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('admin/', admin.site.urls),
path('profile/', profile, name='profile'),
]

url패턴에 logout을 등록한다.

그러면.... 끝났다.

로그아웃을 완성하였다.

단 그냥 만들면 로그아웃시에 account/login으로 리다이렉트되게 되어있다.

우리가 로그인시 쓰는건 그냥 login이므로 리다이렉트 경로를 바꿔줘야한다.

마찬가지로 settings.py를 수정해주자.


# settings.py
LOGIN_REDIRECT_URL = '/profile'
LOGOUT_REDIRECT_URL = '/login'

이제 다시 테스트를 해보자.

제대로 작동하는것을 확인할 수 있을 것이다.


이까지도 좋지만 잘 생각해보면 특정 url를 로그인 했을때만 접근하는 것도 가능하지 않나 싶을 수있다.

물론 지금도 그게 가능하지만 정말 엘레강스한 방법이 있다.

그 방법을 통하여 제작해 보도록하자. 가령 profile페이지를 로그인 해야만 접근할 수있도록 해보자.


# views.py
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.shortcuts import render


# Create your views here.
class IndexView(View):
def get(self, request, *args, **kwargs):
context = {'parm1': 'hello', 'parm2': 'django', 'auth': request.user.is_authenticated}
print(request.user)
return render(request, 'index.html', context=context)

@login_required
def profile(request):
data = {'last_login': request.user.last_login, 'username': request.user.username,
'password': request.user.password, 'is_authenticated': request.user.is_authenticated}
return render(request, 'profile.html', context={'data': data})

이 때 필요한게 login_required 데커레이터이다.

이 데커레이터가 붙어있는 함수는 반드시 로그인을 해야한다.

만약 로그인이 되어있지 않다면 로그인 경로로 이동하게 된다.

기본적으로 로그인 경로는 아무 손을 대지 않을 경우 accounts/login으로 되어있다.

우리는 로그인 경로를 login으로 하므로 이 역시 수정해야한다.

이 수정역시 settings.py에서 할 수 있다.


# settings.py
LOGIN_REDIRECT_URL = '/profile'
LOGOUT_REDIRECT_URL = '/login'
LOGIN_URL = '/login'

이제 로그인에 실패할 경우 해당 경로로 갈 수 있다.


위의 경우에는 function based view이다. 만약 class based view라면 어떻게 해야할까?
class는 데커레이터를 달 수 없다. 그렇기에 mixin이라는 것을 사용한다.

아직 정확히 뭔지는 몰라도되고 굳이 말하자면 편리한 기능들의 집합이라고 생각하면 편하다.


# views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.shortcuts import render


# Create your views here.
class IndexView(View):
def get(self, request, *args, **kwargs):
context = {'parm1': 'hello', 'parm2': 'django', 'auth': request.user.is_authenticated}
print(request.user)
return render(request, 'index.html', context=context)


class ProfileView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
data = {'last_login': request.user.last_login, 'username': request.user.username,
'password': request.user.password, 'is_authenticated': request.user.is_authenticated}
return render(request, 'profile.html', context={'data': data})

class based view로 변형시에 LoginRequiredMixin이 필요하다.

이를 다중 상속해줄경우에 이하의 페이지에는 로그인이 반드시 필요로 하게된다.

'Programming > Python-Django' 카테고리의 다른 글

[Django-09]class based view  (0) 2018.02.11
[Django-08]form과 model연결  (0) 2018.02.03
[Django-07]form만들기  (0) 2018.02.03
[Django-06]model을 templates로 출력하기  (0) 2018.02.03
[Django-05]db와 model 사용하기  (0) 2018.02.03

+ Recent posts