Django搭建個人部落格:使用者的註冊
使用者註冊時會用到表單
來提交賬號、密碼等資料,所以需要寫註冊用的表單/userprofile/forms.py
:
/userprofile/forms.py ... # 註冊使用者表單 class UserRegisterForm(forms.ModelForm): # 複寫 User 的密碼 password = forms.CharField() password2 = forms.CharField() class Meta: model = User fields = ('username', 'email') # 對兩次輸入的密碼是否一致進行檢查 def clean_password2(self): data = self.cleaned_data if data.get('password') == data.get('password2'): return data.get('password') else: raise forms.ValidationError("密碼輸入不一致,請重試。") 複製程式碼
上一章也講過,對資料庫進行操作的表單應該繼承forms.ModelForm
,可以自動生成模型中已有的欄位。
這裡我們覆寫了password
欄位,因為通常在註冊時需要重複輸入password
來確保使用者沒有將密碼輸入錯誤,所以覆寫掉它以便我們自己進行資料的驗證工作。def clean_password2()
中的內容便是在驗證密碼是否一致了。def clean_[欄位]
這種寫法Django會自動呼叫,來對單個欄位的資料進行驗證清洗。
覆寫某欄位之後,內部類class Meta
中的定義對這個欄位就沒有效果了,所以fields
不用包含password
。
需要注意:
-
驗證密碼一致性方法不能寫
def clean_password()
,因為如果你不定義def clean_password2()
方法,會導致password2中的資料被Django判定為無效資料從而清洗掉,從而password2
屬性不存在。最終導致兩次密碼輸入始終會不一致,並且很難判斷出錯誤原因。 -
從POST中取值用的
data.get('password')
是一種穩妥的寫法,即使使用者沒有輸入密碼也不會導致程式錯誤而跳出。前面章節提取POST資料我們用了data['password']
,這種取值方式如果data中不包含password
,Django會報錯。另一種防止使用者不輸入密碼就提交的方式是在表單中插入required
屬性,後面會講到。
檢視函式
編寫註冊的檢視/userprofile/views.py
:
/userprofile/views.py # 引入 UserRegisterForm 表單類 from .forms import UserLoginForm, UserRegisterForm # 使用者註冊 def user_register(request): if request.method == 'POST': user_register_form = UserRegisterForm(data=request.POST) if user_register_form.is_valid(): new_user = user_register_form.save(commit=False) # 設定密碼 new_user.set_password(user_register_form.cleaned_data['password']) new_user.save() # 儲存好資料後立即登入並返回部落格列表頁面 login(request, new_user) return redirect("article:article_list") else: return HttpResponse("登錄檔單輸入有誤。請重新輸入~") elif request.method == 'GET': user_register_form = UserRegisterForm() context = { 'form': user_register_form } return render(request, 'userprofile/login.html', context) else: return HttpResponse("請使用GET或POST請求資料") 複製程式碼
邏輯上結合了發表文章檢視 和使用者登入檢視 ,沒有新的知識。
使用者在註冊成功後會自動登入並返回部落格列表頁面。
模板和url
表單有關的模板檔案我們也很熟悉了,新建/templates/userprofile/register.html
:
/templates/userprofile/register.html {% extends "base.html" %} {% load staticfiles %} {% block title %} 登入 {% endblock title %} {% block content %} <div class="container"> <div class="row"> <div class="col-12"> <br> <form method="post" action="."> {% csrf_token %} <!-- 賬號 --> <div class="form-group col-md-4"> <label for="username">暱稱</label> <input type="text" class="form-control" id="username" name="username" required> </div> <!-- 郵箱 --> <div class="form-group col-md-4"> <label for="email">Email</label> <input type="text" class="form-control" id="email" name="email"> </div> <!-- 密碼 --> <div class="form-group col-md-4"> <label for="password">設定密碼</label> <input type="password" class="form-control" id="password" name="password" required> </div> <!-- 確認密碼 --> <div class="form-group col-md-4"> <label for="password2">確認密碼</label> <input type="password" class="form-control" id="password2" name="password2" required> </div> <!-- 提交按鈕 --> <button type="submit" class="btn btn-primary">提交</button> </form> </div> </div> </div> {% endblock content %} 複製程式碼
上面的模板檔案中,我們在暱稱、密碼input
標籤中添加了required
屬性(前面提到過)。如果使用者不填寫帶有required
屬性的欄位,表單就不能提交,並提示使用者填寫。實際上前面學習的很多表單都可以新增required
屬性來提前驗證資料的有效性。
註冊的入口你可以放在任何喜歡的地方。本文放在登入頁面中/templates/userprofile/login.html
:
/templates/userprofile/login.html ... <div class="col-12"> <br> <h5>還沒有賬號?</h5> <h5>點選<a href='{% url "userprofile:register" %}'>註冊賬號</a>加入我們吧!</h5> <br> <form method="post" action="."> ... </form> </div> ... 複製程式碼
最後就是在app中配置路由檔案/userprofile/urls.py
了:
/userprofile/urls.py ... urlpatterns = [ ... # 使用者註冊 path('register/', views.user_register, name='register'), ] 複製程式碼