24.優化模板 html
在這個項目中,從已經作過的模板來看,你可能會注意到裏面有不少重複的代碼。這種重複不只帶來大量無謂的工做量,並且之後調整起來也極爲不便。python
所以,最理想的作法是將那些重複的代碼放到基礎模板中,而後從基礎模板再擴展出一個個新的模板。chrome
咱們先來作這個基礎模板,在templates文件夾下新建一個base.html文件,而後添加如下內容:django
templates/base.html:瀏覽器
<!DOCTYPE html> <html> <head> <title>Rango - {% block title %}實戰Django!{% endblock %}</title> </head> <body> <div> {% block body_block %}{% endblock %} </div> <hr /> <div> <ul> {% if user.is_authenticated %} <li><a href="/rango/restricted/">限制頁面</a></li> <li><a href="/rango/logout/">註銷</a></li> <li><a href="/rango/add_category/">新建分類</a></li> {% else %} <li><a href="/rango/register/">註冊</a></li> <li><a href="/rango/login/">登陸</a></li> {% endif %} <li><a href="/rango/about/">關於</a></li> </ul> </div> </body> </html>
咱們來修改一下category.html這個模板,把內容改爲下面這樣:安全
templates/rango/category.html:服務器
{% extends 'base.html' %} {% load staticfiles %} {% block title %}` category_name `{% endblock %} {% block body_block %} <h1>` category_name `</h1> {% if category %} {% if pages %} <ul> {% for page in pages %} <li><a href="` page`.`url `">` page`.`title `</a></li> {% endfor %} </ul> {% else %} <strong>當前分類下尚無可用頁面!</strong> {% endif %} {% if user.is_authenticated %} <a href="/rango/category/`category`.`slug`/add_page/">添加頁面</a> {% endif %} {% else %} 指定的分類名稱 ` category_name ` 不存在! {% endif %} {% endblock %}
注意,咱們在第一行中寫了一句」{% extends 'rango/base.html' %} 「,它表示本模板繼承了base.html這個模板,這樣咱們在這個模板中就只需專一添加」block title「和」body_block 「這兩塊就行!cookie
咱們能夠用一樣的方式對其它的模板進行處理。網絡
在基礎模板中,咱們還能夠直接引用url的名稱。好比「關於」頁面的連接,原來寫的是:「session
templates/rango/base.html:
<li><a href="{% url 'about' %}">關於</a></li>
當程序看到「{% url …}」的時候,它會自動去urls.py文件中找相應的名稱(好比說」about」).這樣寫的好處是,之後當咱們要修改連接時,沒必要去逐個改動模板,而只要在urls.py中進行修改就能夠了!
」關於「這個頁面的連接咱們還能夠這樣寫:
<li><a href="{% url 'rango.views.about' %}">關於</a></li>
這至關於告訴程序,到」rango」這個應用中,找一個叫」about」的視圖。不過我仍是更喜歡前面一種寫法。
咱們能夠將base.html模板中的那些連接寫成這樣:
templates/rango/base.html(更新</body>前面的最後一個<div>標籤裏的內容):
<div> <ul> {% if user.is_authenticated %} <li><a href="{% url 'restricted' %}">限制頁面</a></li> <li><a href="{% url 'logout' %}">註銷</a></li> <li><a href="{% url 'add_category' %}">新建分類</a></li> {% else %} <li><a href="{% url 'register' %}">註冊</a></li> <li><a href="{% url 'login' %}">登陸</a></li> {% endif %} <li><a href="{% url 'about' %}">關於</a></li> </ul> </div>
咱們再來看看首頁模板,在index.html中,咱們能夠用一樣的方式來改造。
好比category的連接,咱們能夠寫成:
templates/rango/index.html(找不到麼?用第一行代碼搜索一下!):
{% for category in categories %} <!-- 下面這行給分類加入了超連接 --> <li><a href="{% url 'category' category.slug %}">` category`.`name `</a></li> {% endfor %}
你能夠嘗試將全部的連接都改寫過來,捨得建議你們一開始就養成這樣寫的習慣。
25.Cookies(信息指紋)和Sessions(會話)
Cookies和Sessions在當今的網絡應用程序中是極爲重要的。事實上在以前咱們講到登陸和註銷的模塊時,咱們已經用到了Cookies和Sessions,只不過沒告訴你罷了。如今咱們來看看Cookies和Sessions在其它方面的應用。
先來段測試。找到rango/views.py,在index視圖的第一行插入以下代碼:
rango/views.py:
request.session.set_test_cookie()
而後找到register視圖,在第一行插入下面三行代碼:
if request.session.test_cookie_worked(): print (">>>> TEST COOKIE WORKED!") request.session.delete_test_cookie()
加完上面這些代碼(注意縮進哦),在瀏覽器的地址欄中輸入:
http://127.0.0.1:8000/rango/
而後點擊」註冊「連接,你應該能夠在你的Django服務器控制檯(Dos命令提示符下,還記得執行」python manage.py runserver」的地方不?)下看到以下的字樣:
>>>> TEST COOKIE WORKED!
若是看不到,多是你的瀏覽器中禁用了Cookies。
好了,剛纔只是一個測試,如今你能夠刪掉添加那幾行代碼,繼續往下看。
咱們知道cookies已經能正常工做了,讓咱們來作一個很是簡單的站點訪問數統計。要實現這項功能,咱們須要作兩個cookies,一個用來記錄用戶訪問Rango的次數,另外一個則用來記錄用戶上一次訪問Rango的時間,第二個cookies能夠幫助咱們統計那些一天內頻繁訪問Rango的用戶,無論他一天訪問多少次,咱們只算他一次的訪問量。
編輯rango/views.py,修改index視圖:
rango/views.py:
def index(request): category_list = Category.objects.all() page_list = Page.objects.order_by('-views')[:5] context_dict = {'categories': category_list, 'pages': page_list} # 獲取站點的訪問量 # 咱們用COOKIES.get()方法來獲取cookie中的訪問數據 # 若是cookie存在,則把返回的數值轉成整數 # 若是cookie不存在,則將visits值設定爲0 visits = int(request.COOKIES.get('visits', '0')) reset_last_visit_time = False # cookie中有last_visit這個值嗎? if 'last_visit' in request.COOKIES: # 好滴,果真有這個值 last_visit = request.COOKIES['last_visit'] # 將這個值用python的datetime庫轉換爲特定的日期格式 last_visit_time = datetime.strptime(last_visit[:-7], "%Y-%m-%d %H:%M:%S") # 若是從上次登陸到如今已經超過一天,則訪問數加1... if (datetime.now() - last_visit_time).days > 0: visits = visits + 1 # ...將重置last_visit時間的信號設爲True,表示此值須要更新 reset_last_visit_time = True else: # Cookie中沒有last_visit值, 也將重置last_visit時間的信號設爲True reset_last_visit_time = True context_dict['visits'] = visits # 先渲染出response對象,以便增長cookie信息 response = render(request, 'rango/index.html', context_dict) if reset_last_visit_time: response.set_cookie('last_visit', datetime.now()) response.set_cookie('visits', visits) # 將response對象返回給用戶,更新需更改的cookie值 return response
由於咱們這裏用到了Python的datetime庫,別忘了在文件頭部加入這樣一句:
from datetime import datetime
咱們來看一下效果,在谷歌瀏覽器(chrome)中輸入:http://127.0.0.1:8000/rango/,首頁出現了。
若是想看到訪問數據,須要作如下幾步操做:
若是visits數據爲0,不妨修改一下系統時間(改到明天便可),而後再刷新瀏覽器的頁面,你就能夠觀察到數據的變化了。
上面這個例子的訪問數據是儲存在用戶的電腦上的,然而,更安全也更經常使用的作法是將會話信息儲存到服務器上。
要使用基於cookie的會話,你須要檢查一下Rango的環境:
若是你在前面一步步作下來,那麼這兩項都應該符合要求的。
咱們再來編輯rango/views.py,修改index視圖:
rango/views.py:
def index(request): category_list = Category.objects.order_by('-likes')[:5] page_list = Page.objects.order_by('-views')[:5] context_dict = {'categories': category_list, 'pages': page_list} visits = request.session.get('visits') if not visits: visits = 0 reset_last_visit_time = False last_visit = request.session.get('last_visit') if last_visit: last_visit_time = datetime.strptime(last_visit[:-7], "%Y-%m-%d %H:%M:%S") if (datetime.now() - last_visit_time).seconds > 0: # ...訪問數加1... visits = visits + 1 # ...發出更新last_visit值的信號 reset_last_visit_time = True else: # last_visit值不存在,發出建立last_visit值的信號. reset_last_visit_time = True context_dict['visits'] = visits request.session['visits'] = visits if reset_last_visit_time: request.session['last_visit'] = str(datetime.now()) response = render(request,'rango/index.html', context_dict) return response
【未完待續】