Photo by Charles Koh on Unsplash
現今大多數的網站中,只要有會員的機制,都會有登入驗證及註冊的影子,是網站中不可或缺的功能,並且非常的重要,而Python的Django框架,也提供了相關的實作,本文就帶大家來瞭解。
在[Django教學7]透過Django ModelForm快速開發CRUD應用程式教學文章中,利用實作CRUD的應用程式,瞭解了Django基本的表單運作模式後,本文將分享另外兩種表單類別的使用方式,分別為UserCreationForm及Form類別,接著應用在網站的登入及註冊功能,重點包含:
在[Django教學7]透過Django ModelForm快速開發CRUD應用程式教學文章中,利用實作CRUD的應用程式,瞭解了Django基本的表單運作模式後,本文將分享另外兩種表單類別的使用方式,分別為UserCreationForm及Form類別,接著應用在網站的登入及註冊功能,重點包含:
- Django建立首頁畫面
- Django UserCreationForm(新增使用者表單)
- Django UserCreationForm實作註冊功能
- Django UserCreationForm客製化
- Django Form實作登入功能
- Django實作登出功能
- Django登入驗證裝飾詞(Decorators)
一、Django建立首頁畫面
在進行今天的實作之前,可以先建立Django應用程式(APP)的首頁畫面,讓等一下使用者註冊成功且登入後,進行畫面的導向使用。建立的方式可以參考[Django教學5]Django Template(樣板)開發快速上手文章,來建立簡單的首頁畫面。而本文所使用的首頁檢視函式(View Function)、首頁樣板(index.html)及執行結果如下:
views.pyfrom django.shortcuts import render
#首頁
def index(request):
return render(request, 'accounts/index.html')
index.html執行結果{% extends 'base.html' %} {% block content %} {% endblock %}Django AuthDev HomPage
This example is a quick demo to illustrate how django authentication works.
登出 »
二、Django UserCreationForm(新增使用者表單)
UserCreationForm(新增使用者表單)是Django專案中,auth應用程式(APP)所提供,從settings.py的INSTALLED_APPS可以看到,如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles'
]
並且,相對應的資料模型(Model)及表單類別,Django都預設建立完成,所以,在Django Administration後台,才會看到Users這個資料表,如下圖:
而UserCreationForm(新增使用者表單)就是在上圖按下Add按鈕新增使用者時,所要填寫的表單,這時候就能夠加以利用,來開發網站的註冊功能。
三、Django UserCreationForm實作註冊功能
接下來,就可以使用Django所提供的UserCreationForm來開發網站的註冊功能。首先引用UserCreationForm類別,接著,建立註冊檢視函式(View Function),並且初始化UserCreationForm表單,如下範例:
from django.shortcuts import render
from django.contrib.auth.forms import UserCreationForm
#首頁
def index(request):
return render(request, 'accounts/index.html')
#註冊
def sign_up(request):
form = UserCreationForm()
context = {
'form': form
}
return render(request, 'accounts/register.html', context)
完成註冊檢視函式(View Function)後,開啟應用程式(APP)下的urls.py,設定註冊的網址,如下範例:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='Index'),
path('register', views.sign_up, name='Register')
]
新增註冊樣板(Template),將UserCreationForm顯示在註冊畫面中,如下範例:{% endblock %} 執行結果{% extends 'base.html' %} {% block content %} AuthDev
註冊
上圖即是Django UserCreationForm的預設顯示方式,分別有帳號、密碼及密碼確認欄位。由於範例中,將整個form物件進行顯示,所以會看到圖中有許多的表單驗證訊息,在等一下進行Django UserCreationForm客製化時,就不會出現了。
有了註冊表單後,下一步就能夠在檢視函式(View Function)中,接收使用者的註冊資料,進行儲存的動作,之後導向到登入畫面,如下範例:
有了註冊表單後,下一步就能夠在檢視函式(View Function)中,接收使用者的註冊資料,進行儲存的動作,之後導向到登入畫面,如下範例:
# 註冊
def sign_up(request):
form = RegisterForm()
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect('/login') #重新導向到登入畫面
context = {
'form': form
}
return render(request, 'accounts/register.html', context)
當使用者資料填寫完成且儲存後,即可到Django Administration(管理員後台)的Users資料表驗證使用者是否有成功新增置資料庫中,如下圖:
透過簡潔的幾行程式碼,即可做到基本的註冊功能,Django在背後幫我們進行了註冊表單的資料驗證、密碼的雜湊(Hash)處理及帳號是否已存在等,非常的強大。
四、Django UserCreationForm客製化
如果想要客製化註冊的顯示欄位,可以參考[Django教學7]透過Django ModelForm快速開發CRUD應用程式教學文章的觀念,在Django應用程式(APP)下的forms.py中,引用UserCreationForm類別及User資料模型,接著建立自己的註冊表單類別,繼承自UserCreationForm後,來進行客製化,如下範例:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
username = forms.CharField(
label="帳號",
widget=forms.TextInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(
label="電子郵件",
widget=forms.EmailInput(attrs={'class': 'form-control'})
)
password1 = forms.CharField(
label="密碼",
widget=forms.PasswordInput(attrs={'class': 'form-control'})
)
password2 = forms.CharField(
label="密碼確認",
widget=forms.PasswordInput(attrs={'class': 'form-control'})
)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
範例中,除了增加欄位的CSS類別外,也增加顯示email電子郵件欄位,最後,在檢視函式(View Function)中,將原來的UserCreationForm類別替換為自行建立的RegisterForm擴充類別,如下範例:
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from .forms import RegisterForm
#首頁
def index(request):
return render(request, 'accounts/index.html')
#註冊
def sign_up(request):
form = RegisterForm()
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
redirect('/login') #重新導向到登入畫面
context = {
'form': form
}
return render(request, 'accounts/register.html', context)
執行結果五、Django Form實作登入功能
註冊功能建立完成後,接著就來利用Django另一個常用的Form類別,來實作登入的功能。而這個Form類別與[Django教學7]透過Django ModelForm快速開發CRUD應用程式教學文章中所介紹的ModelForm不一樣的地方是,ModelForm以資料模型為導向,所以需事先建立資料模型,接著利用其中的屬性欄位來建立表單,所以擁有便捷的資料儲存方法(Method)。而Form類別則是一般的表單,可以不需要建立資料模型即可使用。
由於這邊的登入畫面純粹只是顯示表單,沒有要建立相對應的資料模型,所以使用Django的Form類別來建立表單。使用的方式同樣在應用程式(APP)下的forms.py中,建立登入表單類別,並且繼承自Form類別,如下範例:
由於這邊的登入畫面純粹只是顯示表單,沒有要建立相對應的資料模型,所以使用Django的Form類別來建立表單。使用的方式同樣在應用程式(APP)下的forms.py中,建立登入表單類別,並且繼承自Form類別,如下範例:
class LoginForm(forms.Form):
username = forms.CharField(
label="帳號",
widget=forms.TextInput(attrs={'class': 'form-control'})
)
password = forms.CharField(
label="密碼",
widget=forms.PasswordInput(attrs={'class': 'form-control'})
)
而其中的屬性欄位使用方式與ModelForm類別大同小異。接著,回到檢視函式(View Function),新增登入檢視函式(View Function),將剛剛所定義的登入表單傳到登入頁面(login.html),如下範例:
#登入
def sign_in(request):
form = LoginForm()
context = {
'form': form
}
return render(request, 'accounts/login.html', context)
建立登入頁面樣板(Template),如下範例:{% endblock %} 範例中的註冊按鈕,利用Django的url樣板語法,來導向到註冊的畫面。最後,開啟應用程式(APP)下的urls.py,設定登入畫面的網址,如下範例:{% extends 'base.html' %} {% block content %} AuthDev
登入
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='Index'),
path('register', views.sign_up, name='Register'),
path('login', views.sign_in, name='Login')
]
執行結果
接下來,就要來驗證使用者所輸入的帳號及密碼是否正確,這時候就可以在檢視函式(View Function)中引用Django的auth應用程式(APP)方法(Method),如下範例:
from django.contrib.auth import authenticate, login, logout
登入時,就可以將使用者所輸入的帳號及密碼,傳入authenticate方法(Method)進行驗證,如果通過,則利用login()方法(Method)將使用者進行登入的動作,如下範例:
#登入
def sign_in(request):
form = LoginForm()
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/') #重新導向到首頁
context = {
'form': form
}
return render(request, 'accounts/login.html', context)
這時候在登入畫面輸入剛剛所註冊的使用者帳號後,則可以成功登入。
六、Django實作登出功能
使用者登入後,接下來的登出功能,則可以利用logout()方法(Method)來實作。開啟檢視函式(View Function),定義登出檢視函式(View Function),在成功登出後,重新導向到登入畫面,如下範例:
# 登出
def log_out(request):
logout(request)
return redirect('/login') #重新導向到登入畫面
接著,在urls.py中設定登出網址,如下範例:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='Index'),
path('register', views.sign_up, name='Register'),
path('login', views.sign_in, name='Login'),
path('logout', views.log_out, name='Logout')
]
最後,在首頁的登出按鈕,設定相對應的網址,如下範例:
{% extends 'base.html' %} {% block content %} {% endblock %}Django AuthDev HomPage
This example is a quick demo to illustrate how django authentication works.
登出 »
七、Django登入驗證裝飾詞(Decorators)
實務上,為了防止使用者在沒有進行登入的動作時,直接透過網址存取首頁,這時候就可以引用login_required裝飾詞(Decorators),如下範例:
from django.contrib.auth.decorators import login_required
在需要登入才可存取的檢視函式(View Function)上,加上@login_required標籤,並且設定登入頁面的名稱,如下範例:
# 首頁
@login_required(login_url="Login")
def index(request):
return render(request, 'accounts/index.html')
範例中,當使用者未登入,而存取首頁的網址時,Django就會自動將使用者導向到登入畫面。
八、小結
以上就是利用Python的Django網站框架,來實作登入驗證及註冊的功能,希望透過此教學,讓大家能夠瞭解Django所提供的內建表單類別,並且充分利用,提升網站開發的效率。
如果您喜歡我的文章,請幫我按五下Like(使用Google或Facebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。
如果您喜歡我的文章,請幫我按五下Like(使用Google或Facebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。
GitHub網址:https://github.com/mikeku1116/django-authdev.git
- [Django教學1]3步驟快速安裝Django網站框架
- [Django教學2]建立Django應用程式(APP)
- [Django教學3]Django Migration(資料遷移)的重要觀念
- [Django教學4]實用的Django Administration操作及客製化技巧
- [Django教學5]Django Template(樣板)開發快速上手
- [Django教學6]Django Template(樣板)整合Bootstrap實戰教學
- [Django教學7]透過Django ModelForm快速開發CRUD應用程式教學
- 5個必知的Python Function觀念整理
- Python學習資源整理
作者已經移除這則留言。
回覆刪除您好 我想請教
回覆刪除我的RegisterForm()都一直顯示未定義 我是有需要import甚麼或宣告甚麼嗎?
我看我的程式碼應該都跟您的一樣才對
謝謝
def sign_up(request):
form = RegisterForm()
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect("/login") #重新導向登入畫面
context ={
'form': form
}
return render(request, 'accounts/register.html', context)
還有redirect也都undefined
刪除Kai您好:
刪除1.RegisterForm()顯示未定義:檢查forms.py檔案中是否有定義RegisterForm類別,以及在views.py檔案中是否有進行引入(from .forms import RegisterForm)。
2.redirect也都undefined:意思是您所導向的網址沒有定義,所以要檢查urls.py檔案是否有設定您所導向的網址。
希望以上有解決您的問題 :)
如果是說,
刪除三、Django UserCreationForm實作註冊功能
第四章圖中的
...
form = RegisterForm()
if request.method == "POST":
form = RegisterForm(request.POST)
...
這裡應該還沒帶入form的RegisterForm資料
應該可以先嘗試:
...
form = UserCreationForm()
if request.method == "POST":
form = UserCreationForm(request.POST)
...
就可以輸入資料了,因為我也在測試中
然後再來更深入~~
四、Django UserCreationForm客製化
才會講到RegisterForm
MIKE大您好,我最後可以成功實作本文的流程,
回覆刪除但發生一個問題
不論我怎麼註冊新帳號,皆是只有帳號admin 密碼0000,可以被登入,
貌似他被暫存起來,即便我把這一組資訊刪除,他還是可以登入,
想要請問可能是哪裡出錯??
XIAO您好,在使用者註冊成功後,檢查一下Django Administrator的User資料模型,是否有新的使用者資料? 有的話是否可以成功登入呢? 以上這兩個問題希望能夠幫助您在實作上的偵錯,瞭解可能哪一個階段發生問題,如果還是無法解決的話,歡迎到Learn Code With Mike粉絲專頁私訊我來協助您,謝謝 :)
刪除Mike大您好,我想請問:
回覆刪除目前我已經實作上述範例,連同google登入一併建置好,
然而遇到一種情況,那就是使用一般登入後,無法導入到index頁面去顯示成功登入,但是使用google帳號登入就有成功導入index頁面,請問有可能發生什麼情況嗎?
還望大大幫助我解答疑惑,謝謝!