3번째 줄: |
3번째 줄: |
| 유저들의 권한, 정보에 관한 것들. | | 유저들의 권한, 정보에 관한 것들. |
| | | |
| + | |
| + | ==URL작성== |
| + | 필요한 기능에 대해 생각하고 url을 짠다.<syntaxhighlight lang="python"> |
| + | from django.urls import path |
| + | from django.contrib.auth import views as auth_views #장고에서 제공하는 기능 활용! |
| + | |
| + | app_name = 'membership' |
| + | |
| + | urlpatterns = [ |
| + | path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), |
| + | path('logout/', auth_views.LogoutView.as_view(), name='logout'), |
| + | ] |
| + | |
| + | </syntaxhighlight>심지어 뷰를 안만들어도 된다. |
| + | *registration/login.html 을 기본옵션으로 하지만, 따로 디렉터리를 만드는 것은 낭비다. 때문에 template_name 변수를 따로 지정했다. |
| + | *로그아웃 뷰에선 기본 탬플릿이 없지만, template_name을 지정하면 로그아웃 후 redirect할 탬플릿을 지정할 수 있다. |
| + | ==네비게이션 바에 로그인 버튼 만들기== |
| + | 네비게이션 바 html 적당한 곳에 다음을 삽입한다.<syntaxhighlight lang="html"> |
| + | <!--로그인, 로그아웃 기능--> |
| + | {% if user.is_authenticated %} |
| + | <p>{{ user.username }}</p><a class="nav-link" href="{% url 'membership:logout' %}">(로그아웃)</a> |
| + | <!--로그아웃버튼과 함께 기본적인 정보를 띄워준다.--> |
| + | {% else %} |
| + | <a class="nav-link" href="{% url 'membership:login' %}">로그인</a> |
| + | {% endif %} |
| + | </syntaxhighlight>user의 속성을 이용해 로그인 상태일 때와 아닐 때의 형식이 다르게 만들었다. |
| + | ==탬플릿 만들기== |
| + | ===login.html=== |
| + | 기본적으로 id와 password를 입력하게 되어 있는데, 분명 모델에선 identifier를 식별필드로 지정했는데, 이 코드를 USERNAME_FIELD에 지정하기 때문인지, form 안엔 username으로 받아들이게끔 구성되어 있다. 즉, 식별필드가 무엇이든 username이라는 이름을 사용해서 로그인이 이루어지게 된다.<syntaxhighlight lang="html+django"> |
| + | {% extends "base.html" %} |
| + | |
| + | {% block content %} |
| + | <form method="post" action="{% url 'account:login' %}"> |
| + | {% csrf_token %} |
| + | <!-------------------------------------- 입력에 에러가 났을 때 불러올 html--> |
| + | {% include "form_errors.html" %} |
| + | <!-------------------------------------- 입력을 위한 공간--> |
| + | <div class="form-group"> |
| + | <label for="username">ID</label> |
| + | <input type="text" class="form-control" name="username" id="username" |
| + | value="{{ form.username.value|default_if_none:'' }}"> |
| + | </div> |
| + | <div class="form-group"> |
| + | <label for="password">비밀번호</label> |
| + | <input type="password" class="form-control" name="password" id="password" |
| + | value="{{ form.password.value|default_if_none:'' }}"> |
| + | </div> |
| + | <button type="submit" class="btn btn-primary">로그인</button> |
| + | |
| + | <input type="hidden" name="next" value="{{ next }}"><!--로그인 성공 후 이전 페이지로 이동하게끔 하는 기능--> |
| + | </form> |
| + | {% endblock %} |
| + | </syntaxhighlight> |
| + | ===form_errors.html=== |
| + | account 앱과 관련한 모든 에러메시지를 관리하기 위해 에러메시지만 띄우는 탬플릿을 만든다. 일괄적, 일관적으로 모든 공간에 적용할 수 있게끔. |
| + | |
| + | 에러가 발생했을 때 에러메시지를 띄울 html을 불러온다.<syntaxhighlight lang="html+django"> |
| + | {% if form.errors %} |
| + | {% for field in form %} |
| + | <!------------------------- 필드 오류를 출력 --> |
| + | {% for error in field.errors %} |
| + | <div class="alert alert-danger"> |
| + | <strong>{{ field.label }}</strong> |
| + | {{ error }} |
| + | </div> |
| + | {% endfor %} |
| + | {% endfor %} |
| + | <!----------------------- 넌필드 오류를 출력 --> |
| + | {% for error in form.non_field_errors %} |
| + | <div class="alert alert-danger"> |
| + | <strong>{{ error }}</strong> |
| + | </div> |
| + | {% endfor %} |
| + | {% endif %} |
| + | </syntaxhighlight>필드오류 : 사용자가 form 양식에 맞지 않는 데이터를 입력했을 때. |
| + | |
| + | 넌필드오류 : 기타 등등 에러 |
| + | ==로그인, 로그아웃 성공 후 이동할 url 만들기== |
| + | ===로그인 url=== |
| + | 일반적으로 <code>@login_required(login_url='account:login')</code> 형태로 로그인 url을 써주어야 하지만, 모든 함수에 이걸 써넣긴 어렵고, 수정에도 불편하다. |
| + | |
| + | => settings.py에 <code>LOGIN_URL = 'account:login'</code> 형태로 변수를 지정하면 데코레이터의 괄호에 무언가를 써주지 않아도 잘 기능한다. |
| + | ===로그인 로그아웃 후 리다이렉트=== |
| + | settings.py에서 새로운 설정항목을 만들어주어야 한다. |
| + | {| class="wikitable" |
| + | |+ |
| + | !관련변수 |
| + | !설명 |
| + | !예시 |
| + | |- |
| + | |<code>LOGIN_REDIRECT_URL</code> |
| + | |로그인 후 연결될 주소 설정. |
| + | next 변수를 주어 보던 페이지로 이동하게 할 수도 있다.(다음 내용 참고) |
| + | |
| + | 주소 대신 <code>'앱이름:list'</code> 형태의 인덱스도 가능하다. |
| + | |<code>LOGIN_REDIRECT_URL = '/'</code> |
| + | |- |
| + | |<code>LOGOUT_REDIRECT_URL</code> |
| + | |로그아웃 후 연결될 주소 설정. |
| + | |<code>LOGOUT_REDIRECT_URL = '/'</code> |
| + | |- |
| + | | |
| + | | |
| + | | |
| + | |} |
| + | ===보던 페이지로 돌아가기=== |
| + | 그런데, 사실 로그인 후에 보던 페이지가 안나오면 다시 찾아들어가야 하고.. 불편하다; 다행스럽게도 로그인 기능을 제대로 구현해두면 로그인 페이지로 넘어갈 때 링크가 [http://127.0.0.1:8000/membership/login/?next=/pool/question/create/ http://127.0.0.1:8000/account/login/?next=/보고있던페이지/] 형태로 구성된다. 이전 페이지에 대한 정보를 담고 있는데, 로그인 탬플릿에 다음의 숨겨진 항목을 추가하면 된다.(폼 안에 추가해야 한다.)<syntaxhighlight lang="html+django"> |
| + | <input type="hidden" name="next" value="{{ next }}"> |
| + | </syntaxhighlight>submit은 해당 링크에 대한 정보를 그대로 form으로 보내기에 <nowiki>{{next}}</nowiki>에 있는 이전페이지 주소를 받아 기능한다. 로그인 함수에서 알아서 기능해준다. |
| + | |
| + | [한 가지 의문인 것은... 이전페이지의 정보인 next를 어떻게 가져온거지;;? 이전페이지에서 보내준 것도 아닌데?? 아무래도 데코레이터에 걸리는 듯하다. |
| + | |
| + | 데코레이터에 걸려서 로그인화면으로 넘어가면 next 인자가 생긴다.] |
| + | |
| + | 네비게이션바에 구현한 로그인 버튼은 next인자를 남기지 않는데, 로그인바의 버튼의 주소를.. herf="{% url '인덱스' %}"?next=<nowiki>{{request.path}}</nowiki>" 로 넣어주면 현재 경로를 넘겨줄 수 있다. |
| ==권한== | | ==권한== |
| {| class="wikitable" | | {| class="wikitable" |
69번째 줄: |
184번째 줄: |
| !설명 | | !설명 |
| !코드 | | !코드 |
− | |-
| |
− | |유저 인증
| |
− | |인증 정보를 객체에 담는다.
| |
− | |from django.contrib.auth import authenticate
| |
− | 객체 = authenticate(username=name, password=password)
| |
| |- | | |- |
| |로그인 | | |로그인 |
85번째 줄: |
195번째 줄: |
| logout(request) | | logout(request) |
| |} | | |} |
| + | |
| + | = 뷰 직접 만들기 = |
| + | 제공되는 로그인 뷰를 사용할 수도 있지만, 로그인 중에 특수한 작업을 해야 하는 경우 직접 만들어야만 한다. |
| + | {| class="wikitable" |
| + | !쓸만한 모듈 |
| + | !설명 |
| + | |- |
| + | |<code>from django.contrib.auth.hashers import check_password</code> |
| + | |입력한 패스워드와 저장된 패스워드를 비교한다. |
| + | (입력패스워드는 raw, 저장된 패스워드는 암호화 된 것) |
| + | |- |
| + | |<code>from django.contrib.auth import authenticate</code> |
| + | |<code>user = authenticate(username=식별자, password=쌩비밀번호)</code> |
| + | 인증에 성공하면 user객체가 담기고, 실패하면 None을 반환한다. |
| + | |- |
| + | |<code>from django.contrib.auth import login</code> |
| + | |<code>login(request, user)</code> |
| + | 유저객체를 넣으면 로그인을 진행한다.(비밀번호가 없어도 로그인 된다.) |
| + | |- |
| + | |<code>from django.contrib.auth import logout</code> |
| + | |logout(request) |
| + | |} |
| + | [[분류:장고 기능구현(초급)]] |