owned this note
owned this note
Published
Linked with GitHub
---
tags: python
---
# DAY 27 Django建立使用者帳號
我們今天要來設定一個使者登錄註冊和身分驗證的系統,讓使用者可以註冊帳號,並能夠登入和登出
## user應用程式
首先我們要先用startapp命令來建立名為users應用程式,如下
```python manage.py startapp users```
然後我們可以看現在的learning_log目錄多了users的應用程式,也可以看users目錄裡面的結構跟learning_logs相同,如下
![](https://i.imgur.com/wnZCN0E.png)
### 把users加到setting.py中
將users應用程式引入整個專案中,如下
```python=
INSTALLED_APPS = (
--省略--
'learning_logs',
'users', # 新增區塊
)
```
### 放入users應用程式的URL
我們加了一行程式碼來引入users應用程式中的urls.py檔,這行程式碼與任何以users為開頭的URL都比對符合,如下
```python=
from django.urls import path, include
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')), # 新增區塊
path('', include('learning_logs.urls')),
]
```
## 登入
### 登入的URL模式
我們現在要來做login的頁面,我們會在users資料夾裡面新增一個urls.py檔,如下
```python=
from django.conf.urls import url
from django.urls import path
from django.contrib.auth.views import LoginView
from . import views
app_name='users'
urlpatterns = [
path('login/', LoginView.as_view(template_name='users/login.html'), name="login"),
]
```
上面程式碼我們先在第三行匯入LoginView視圖,第九行是登入頁面的URL模式與URL http://localhost:8000/users/login 相配符合
### 登入模板
使用者請求登入頁面時,Django會使用預設login視圖來處理,但我們還是需要為這個網頁提供模板,首先要在users資料夾裡建立一個templates資料夾,在templates資料夾中再建立一個users資料夾,裡面新增一個login.html,如下
```html=
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'users:login' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">log in</button>
<input type="hidden" name="next"
value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
```
上面程式碼第五行是如果表單errors屬性被設定,就會顯示一條錯誤訊息,回報輸入的使用者名稱-密碼對與資料庫中儲存的都不相符,第十四行這裡放入一個隱藏的表單元素next,其中的引數會告知Django在使用者成功登入後會重新導向主頁
### 連結到登入頁面
:arrow_down: 在base.html中新增連到login頁面的連結,如下
```html=
<p>
--省略--
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>
{% block content %}{% endblock %}
```
上面程式碼第三和第四行是如果使用者已登入就不會顯示連結
:arrow_down: 登入頁面如下
未登入使用者會先看到log in 連結
![](https://i.imgur.com/w9zElZy.png)
點進去後可以輸入使用者帳號和密碼
![](https://i.imgur.com/Fo9l1uP.png)
## 登出
我們現在要來做的是登出,我們不用建立登出頁面,至要讓使用者按一個連結就可以登出並返回主頁
### 登出的URL模式
```python=
--省略--
urlpatterns = [
--省略--
path('logout/', views.logout_view, name='logout'),
]
```
### logout_view()視圖模式
匯入Django的logout()函式並呼叫它,再重新導向主頁,首先我們要開啟users資料夾中的views.py檔,如下
```python=
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout # 匯入logout函式
from django.urls import reverse
def logout_view(request): # 呼叫logout函式,它會把request當作引數,然後重新導向主頁
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))
```
### 連結到logout視圖
:arrow_down: 在base.html中新增連到logout的連結,如下
```html=
<p>
--省略--
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
{% else %}
--省略--
{% endif %}
</p>
{% block content %}{% endblock %}
```
將第五行的logout連結放在if區塊內是因為只有在使用者登入時才能看到logout連結
:arrow_down: 登出連結如下
![](https://i.imgur.com/VcUEErZ.png)
## 登入註冊頁面
這裡要建立讓使用者可以登錄註冊的頁面,我們會使用Django預設提供的UserCreationForm表單
### 登入註冊的URL模式
```python=
--省略--
urlpatterns = [
--省略--
path('register/', views.register, name='register'),
]
```
### register()視圖函式
在登入註冊頁面第一次被請求時,register視圖函是需要顯是一個空的物註冊表單,並在使用者填好資料提交表單時對它進行處理,如果登入註冊成功,這個函式還需要讓使用者登入系統,現在我們要開啟views.py檔來新增一些程式碼,如下
```python=
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.urls import reverse
from django.contrib.auth.forms import UserCreationForm
--省略--
def register(request):
"""Register a new user."""
if request.method != 'POST':
form = UserCreationForm()
else:
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
authenticated_user = authenticate(username=new_user.username,
password=request.POST['password1'])
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)
```
### 登入註冊模板
新增一個register.html檔放在和login.html同一個資料夾,如下
```html=
{% extends "learning_logs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">register</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
```
### 登錄註冊頁面的連結
:arrow_down: 在base.html中新增連到登入頁面的連結,如下
```html=
<p>
--省略--
{% else %}
<a href="{% url 'users:register' %}">register</a> -
--省略--
{% endif %}
</p>
{% block content %}{% endblock %}
```
:arrow_down: 登入註冊連結如下
會看到主頁多了register連結
![](https://i.imgur.com/DxFDmTH.png)
點進來後會看到預設的表單
![](https://i.imgur.com/uWX0488.png)
#### 今天結束,各位明天見 :hand:
***
資料來源:<<python程式設計的樂趣>>-Eric Matthes著/H&C譯