장고(Django) 개발: 사용자 관리

히즈웨드 |

    장고(Django)는 기본적으로 사용자 등록, 로그인(인증), 로그아웃 등 사용자 관리를 위한 모든 객체(django.contrib.auth)와 DB 구성을 제공한다. 공식 위키의 Using the Django authentication system 참고하였다.


    /p>

    작년에 장고(Django) 프레임워크로 프로젝트를 진행하면서 공부했던 개발 지식을 블로그에 다시 정리하려고 합니다. 개인 위키에 정리했던 것을 옮기는 수준이라, 친절한 설명은 기대하기 어렵고, 프로그래밍 언어와 파이썬 지식이 어느정도 있어야 이해할 수 있을 것입니다.


    아래 내용들은 Django 1.6~1.7 버전을 기준으로하고, "쉽고 빠른 웹개발 Django"란 책에서 1/3, 공식 위키에서 1/3, 그리고 나머지는 구글링을 바탕으로 정리한 지식입니다. 말투가 존대와 반말이 섞여있어도 이해바랍니다 :)




    1 사용자 관리 구현 방법

    2 사용자 관리 Views

    3 사용자 로그인

    4 사용자 로그아웃

    5 사용자 비밀번호 변경

    6 사용자 가입




    1 사용자 관리 구현 방법

    첫째, 장고에서 제공하는 사용자 관리 기능을 그대로 사용하는 방법

    • 보다 간편하게 구현 가능하지만, 세부적 수정이 어려움

    둘째, (상속받은) 폼과 프로세스를 커스터마이징 하는 방법

    • 보다 직접적으로 수정가능하지만, 더 많은 코딩이 필요함
    • request.user



    2 사용자 관리 Views

    참고 : django.contrib.auth.views

    views (컨트롤러)
    설명
    login로그인 처리
    logout로그아웃 후 템플릿 출력
    logout_then_login로그아웃 후에 다시 로그인 페이지로 이동
    password_change비밀번호 변경 폼 출력
    password_change_done비밀번호가 정상적으로 변경된 후 출력
    password_reset새로운 비밀번호를 이메일로 전달
    password_reset_done비밀번호 리셋 후 출력
    password_reset_confirm비밀번호를 리셋하는 폼 출력
    password_reset_complete비밀번호 리셋 폼에서 정상적으로 리셋된 후 출력
    redirect_to_login로그인 페이지로 이동

    User 관련 주요 함수

    is_authenticated()                              # 로그인 여부
    get_full_name()                                 # 사용자 성과 이름 모아서 출력
    email.user(subject, message, from_email=None)   # 이메일 보내기
    set_password(raw_password)                      # 비밀번호 변경 (알아서 암호화)
    check_password(raw_password)                    # 원래 비밀번호와 일치하는지 검사



    3 사용자 로그인

    장고에서 제공하는 사용자 관리 기능을 그대로 사용하는 첫번째 방법 사용함

    URL 지정

    django.contrib.auth.views에는 세션과 인증에 관한 다양한 뷰가 존재함

    url(r'^login/$''django.contrib.auth.views.login'),    # 로그인 페이지

    뷰 코드

    django.contrib.auth.views.login에서 기본 제공하는 것이 사용됨

    템플릿 코드

    /템플릿폴더/registration/login.html

    <html>
      <head>
        <title>장고 북마크 - 사용자 로그인</title>
      </head>
      <body>
        <h1>사용자 로그인</h1>
        {% if form.errors %}
          <p>사용자 이름과 비밀번호가 일치하지 않습니다. 다시 시도해보세요.</p>
        {% endif %}
          <form method="post" action=".">{% csrf_token %}
            <p><label for="id_username">사용자 이름:</label>{{ form.username }}</p>
            <p><label for="id_password">비밀번호:</label>{{ form.password }}</p>
            <input type="hidden" name="next" value="/" />
            <input type="submit" value="로그인" />
          </form>
      </body>
    </html>



    4 사용자 로그아웃

    URL 지정

    django.contrib.auth.views에는 세션과 인증에 관한 다양한 뷰가 존재함

    urlpatterns = patterns('',
        url(r'^logout/$', logout_page),                         # 로그아웃 페이지
    )

    뷰 코드

    from django.http import HttpResponseRedirect
    from django.contrib.auth import logout
     
    def logout_page(request):
        logout(request)
        return HttpResponseRedirect('/');

    템플릿 코드

    리다이렉트 되도록 만들었기 때문에 템플릿 없음



    5 사용자 비밀번호 변경

    비밀번호를 변경하는 폼 페이지와 변경완료 됐을 때 리다이렉트 되는 페이지로 구성됨

    장고에서 제공하는 사용자 관리 기능을 그대로 사용하는 첫번째 방법 사용함.

    URL 지정

    url(r'^password_change/$',
        'django.contrib.auth.views.password_change',
        {'post_change_redirect' '/password_change/done/'}),    # 유저 비밀번호 변경 페이지
    (r'^password_change/done/$',
        'django.contrib.auth.views.password_change_done'),       # 유저 비밀번호 변경 완료 페이지

    뷰 코드

    django.contrib.auth.views.password_change 와 password_change_done 에서 기본 제공하는 것이 사용됨

    템플릿 코드

    /템플릿폴더/registration/password_change_form.html

    {% extends "base.html" %}
    {% block title %}사용자 비밀번호 변경{% endblock %}
    {% block head %}사용자 비밀번호 변경{% endblock %}
    {% block content %}
        {% if form.errors %}
            <p>비밀번호가 잘못 되었습니다. 다시 시도해보세요.</p>
        {% endif %}
        <form method="post" action=".">{% csrf_token %}
            <p>{{ form.old_password.errors }}
            <label for="old_password">기존 비밀번호:</label>{{ form.old_password }}</p>
            <p>{{ form.new_password1.errors }}
            <label for="new_password1">새 비밀번호:</label>{{ form.new_password1 }}</p>
            <p>{{ form.new_password2.errors }}
            <label for="new_password2">새 비밀번호 확인:</label>{{ form.new_password2 }}</p>
            <input type="submit" value="비밀번호 변경" />
        </form>
    {% endblock %}

    /템플릿폴더/registration/password_change_done.html

    {% extends "base.html" %}
    {% block title %}사용자 비밀번호 변경 완료{% endblock %}
    {% block head %}사용자 비밀번호 변경이 완료되었습니다.{% endblock %}
    {% block content %}
        <p>사용자 비밀번호 변경이 완료되었습니다.
            이제 <a href="/login/">로그인</a>하시거나,
            아니면 <a href="/">메인</a>으로 이동할 수 있습니다.</p>
    {% endblock %}



    6 사용자 가입

    (상속받은) 폼과 프로세스를 커스터마이징 하는 두번째 방법을 사용함

    URL 지정

    url(r'^register/$', register_page),                          # 가입 페이지

    forms.py 생성

    forms.py는 forms.Form을 상속받아 RegistrationForm 구현

    from django import forms
     
    class RegistrationForm(forms.Form):
        username = forms.CharField(label='사용자 이름', max_length=30)
        email = forms.EmailField(label='이메일')
        password1 = forms.CharField(label='비밀번호', widget=forms.PasswordInput())
        password2 = forms.CharField(label='비밀번호 확인', widget=forms.PasswordInput())

    뷰 코드

    from bookmarks.forms import *
     
    def register_page(request):
        if request.method == 'POST':
            form = RegistrationForm(request.POST)
            if form.is_valid():
                user = User.objects.create_user(
                    username=form.cleaned_data['username'],
                    email=form.cleaned_data['email'],
                    password=form.cleaned_data['password1']
                )
                return HttpResponseRedirect('/register/success/')
        else:
            form = RegistrationForm()
                 
        variables = RequestContext(request, {
            'form': form
        })
             
        return render_to_response('registration/register.html', variables)

    템플릿 코드

    폼 객체를 출력하기 위해서 form.as_table, form.as_p, form.as_ul 사용

    {% extends "base.html" %}
    {% block title %}사용자 가입{% endblock %}
    {% block head %}사용자 가입{% endblock %}
    {% block content %}
        {% if form.errors %}
            <p>사용자 이름과 비밀번호가 일치하지 않습니다. 다시 시도해보세요.</p>
        {% endif %}
        <form method="post" action=".">{% csrf_token %}
            {{ form.as_p }}
            <input type="submit" value="가입" />
        </form>
    {% endblock %}