使用 Django 內建的使用者登入登出系統

3 minute read

Django,Python 中有名的 Web framework 之一。

這篇文章紀錄了,如何利用 Django 內建的 auth 資料結構,在 30 分鐘內快速寫出一個支援登入、登出、註冊功能的網站,並且支援客製化的前端模板。

我認為初學網站框架的人,Django 是最好的選擇,因為 Ruby on Rails 適合已經開發過一些網站的人,NodeJs 因為 asynchronous 的設計,會讓初學者掉入恐怖的 Callback Hell ,Django 雖然需要多寫不少東西,但他的 MTV 框架非常清楚明白,三個部份各司其職,非常助於我們學習網頁框架!

有點離題了,接下來我們回到寫一個支援基本的登入、登出以及註冊的網站吧。

Python 虛擬環境

用 Python 開發東西當然是少不了 virtualenv 這項幫手,它可以幫助建立 Python 開發用的獨立環境。

當然是使用 Python3 了,另外以下的範例都是在 Python3 的環境下執行喔。

virtualenv django-login --python=python3
cd django-login
source ./bin/activate

如果要離開的話輸入 deactivate 即可。

$ pip3 install django
$ django-admin startproject loginsite

我們開始簡單的 login site 教學吧

設定 url 以及 template 位置

url.py

  1. 使用內建的 auth_view,省掉撰寫登入登出驗證的時間,不過 template 還是要自己寫一下,有些小麻煩

  2. 要指定一下 template_name,不然它會去 library 裡面翻,然後就發生悲劇 我其實不太懂為什麼 Django 沒有寫好他的 template,不過沒關係,我們可以自己寫

  3. home 是只有登入的人才能看到的頁面,等一下的 views.py 中會寫到這個邏輯

import django.contrib.auth.views as auth_view
from . import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', auth_view.login, {'template_name': 'login.html'}, name='login'),
    url(r'^logout/', auth_view.logout, {'template_name': 'logout.html'}, name='logout'),
    url(r'^', views.home, name='home'),
]

settings.py

再來,要告訴 django 我們 template 的位置,這裡指定 template 資料夾為 ./loginsite/templates/

這裡我沒有找到 define 好的常數可以用,沒辦法用 BASE_DIR + APP_NAME 的方式做,如果你有找到可以留言告訴我

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
        ],
        
        ...

此外,還要加上 login/logout redirection 的設定,不然需要登入時它又會去 library 亂翻一通XD

LOGIN_URL = '/login/' # 預設 login page 的 url
LOGIN_REDIRECT_URL = '/'  # login 完之後導向的頁面
LOGOUT_REDIRECT_URL = '/' # logout 完之後導向的頁面

撰寫 template

templates/login.html

<h1>Login</h1>
  <form method="post"> {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
</form>

logout.html 不需要寫,我們只要讓使用者可以在首頁點選 logout 就好

templates/home.html

<p>{{username}}, you are already logged-in!</p>
<a href="{% url 'logout' %}"><button>Logout</button></a>

views.py

我們使用方便的 login_required decorator,規定使用者必須登入才能看到這個頁面

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required
def home(request):
    return render(request, 'home.html', {'username': request.user.username})

在此範例中,我讓後端傳給前端 username,並顯示出來

建立測試帳號以供登入

$ python3 manage.py createsuperuser

用這個指令建立的帳號,可以登入 /admin/ 編輯所有的用戶

備註:如果覺得密碼規定很複雜的話,可以把 settings.py 裡面的 AUTH_PASSWORD_VALIDATORS 的東西刪除

至此已經完成了基本的登入,接下來是註冊的部份,我們一樣用 django 內建的 auth 來做

註冊

urls.py

url(r'^register/', views.register, name='register')

view.py

  1. 它佛心的連 User form 都寫好了,所以直接拿來用吧
  2. 如果使用者註冊了一個合法的表單,那我們就把它存入資料庫,並重新導向至登入頁面
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm


def register(request):
    form = UserCreationForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('login')

    return render(request, 'register.html', {'form': form})

templates/register.html

<h1>Register</h1>
  <form method="post"> {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Register</button>
</form>

templates/login.html

把 register 的按鈕加上去:

<h1>Login</h1>
  <form method="post"> {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
</form>
<a href="{% url 'register' %}"><button>Register</button></a>

至此大功告成!

環境

  • Python 3.6
  • Django 1.10.3
  • Virtualenv 15.1.0