你應該注意到了一點,當你去建立、修改和删除文章的時候并不需要登入,這樣的話任何浏覽網站的使用者都能随時修改和删除我的文章。這個可不是我想要的!
編輯和删除的認證
我們需要保護post_new, post_edit和post_publish這三個視圖,隻有登入使用者才有權去執行。 django為我們提供了很好的幫助類,其實就是利用了python中的decorators技術。 django中認證的裝飾器位于子產品django.contrib.auth.decorators中,名稱叫login_required。
編輯blog/views.py檔案,在import部分添加如下的導入語句:
1
| from django.contrib.auth.decorators import login_required
|
然後在post_new, post_edit和post_publish這三個函數上添加@login_required, 類似下面
1
2
3
| @login_required
def post_new(request):
[...]
|
好的,現在你再去通路下http://localhost:8000/post/new/,看看有啥變化。
注:如果你仍然能正常進入建立頁面,那可能是你之前在admin界面登陸過。 那麼你需要先退出,通路http://localhost:8000/admin/logout/可以退出,然後你再看下效果。
我剛剛添加的@login_required裝飾器檢測到你尚未登陸的時候會重定向到login頁面, 但是我現在還沒有定義login的模闆頁面,是以這時候會是404錯誤頁面。
使用者登入
django在使用者認證方面做得很好了,我們隻需要去使用它就行。
在mysite/urls.py檔案中,添加下面一行
1
| url(r'^accounts/login/$', 'django.contrib.auth.views.login')
|
現在這個檔案内容如下:
1
2
3
4
5
6
7
8
9
10
| from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
url(r'', include('blog.urls')),
)
|
然後我們再定義一個登陸頁面,建立目錄mysite/templates/registration, 并在裡面建立模闆檔案login.html,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| {% extends "mysite/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 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<table>
<tr>
<td>` form`.`username`.`label_tag `</td>
<td>` form`.`username `</td>
</tr>
<tr>
<td>` form`.`password`.`label_tag `</td>
<td>` form`.`password `</td>
</tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="` next `" />
</form>
{% endblock %}
|
你可以看到我們仍然使用到了模闆繼承。這個時候可以定義一個mysite/templates/mysite/base.html, 把blog/templates/blog/base.html的内容複制給它即可。
不過我們需要在mysite/settings.py中再添加一個urls配置:
1
| LOGIN_REDIRECT_URL = '/'
|
這樣的話當使用者直接通路login頁面後登入成功會重定向到文章清單頁面去。
改進顯示
現在的确隻有登入使用者才能修改和删除文章,但是未登入使用者卻能看到這些按鈕, 這個是很不好的體驗。現在如果是未登入使用者的話就把這些按鈕給隐藏掉。
是以我們修改mysite/templates/mysite/base.html如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <body>
<div class="page-header">
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
<a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
{% else %}
<a href="{% url 'django.contrib.auth.views.login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a>
{% endif %}
<h1><a href="{% url 'blog.views.post_list' %}">Django Girls</a></h1>
</div>
<div class="content">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
</body>
|
然後修改blog/templates/blog/post_detail.html如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| {% extends 'blog/base.html' %}
{% block content %}
<div class="date">
{% if post.published_date %}
` post`.`published_date `
{% else %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'blog.views.post_publish' pk=post.pk %}">Publish</a>
{% endif %}
{% endif %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
{% endif %}
</div>
<h1>` post`.`title `</h1>
<p>{{ post.text|linebreaks }}</p>
{% endblock %}
|
使用者登出
當使用者登入後顯示歡迎語句,Hello ,然後後面跟一個logout連結。還是依靠django幫我們處理logout動作。
修改mysite/templates/mysite/base.html檔案如下:
1
2
3
4
5
6
7
8
9
10
| <div class="page-header">
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
<a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
<p class="top-menu">Hello ` user`.`username `<small> <a href="{% url 'django.contrib.auth.views.logout' %}">Log out</a></p>
{% else %}
<a href="{% url 'django.contrib.auth.views.login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a>
{% endif %}
<h1><a href="{% url 'blog.views.post_list' %}">Django Girls</a></h1>
</div>
|
很顯然這時候logout肯定會報錯。我們還得做些事情。
對于這方面的詳細文檔請參考:https://docs.djangoproject.com/en/1.9/topics/auth/default/
打開mysite/urls.py檔案,添加一個logout配置:
1
2
3
4
5
6
7
8
9
10
11
| from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}),
url(r'', include('blog.urls')),
)
|
如果通路網站時出現模闆找不到錯誤,那麼你就在mysite/settings.py中添加如下配置:
1
2
3
4
5
| # TEMPLATE_DIRS
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'mysite/templates'),
os.path.join(BASE_DIR, 'blog/templates'),
)
|
好的,現在你已經可以達成如下的效果了:
- 需要一個使用者名和密碼登入系統
- 在添加/編輯/删除/釋出文章的時候需要登入