Django1.8.2中文文檔:Django1.8.2中文文檔
模板
模板注釋
單行注釋:
{# 注釋內容 #}
多行注釋:
{% comment %}
注釋內容
{% endcomment %}
注意,模板注釋和html注釋不同,html注釋后瀏覽器檢查還能看到朱時候的代碼,但模板注釋不能被看到。
模板的功能
產生html,控制頁面上展示的內容。模板文件不僅僅是一個html文件。
模板文件包含兩部分內容:
1)靜態內容:css,js,html。
2)動態內容:用於動態去產生一些網頁內容。通過模板語言來產生。
模板文件的使用
通常是在視圖函數中使用模板產生html內容返回給客戶端。
a)加載模板文件 loader.get_template
獲取模板文件的內容,產生一個模板對象。
b)定義模板上下文 RequeseContext
給模板文件傳遞數據。
c)模板渲染產生html頁面內容 render
用傳遞的數據替換相應的變量,產生一個替換后的標准的html內容。
不用render自己渲染模板示例/ 給一個函數使用templates模板
def index(request): # 1.加載模板文件,獲取一個模板對象 temp = loader.get_template('booktest/index.html') # 2.定義模板上下文,給模板文件傳數據 # context = RequestContext(request, {}) # 在django1.11中不能使用這種方法,只能直接定義一個字典 context = {} # 3.模板渲染,產生一個替換后的html內容 res_html = temp.render(context) # 4.返回應答 return HttpResponse(res_html)
自定義render渲染模板示例/ 抽離出templates渲染函數給多個視圖函數使用
def my_render(request, template_path, context={}): # 1.加載模板文件,獲取一個模板對象 temp = loader.get_template(template_path) # 2.定義模板上下文,給模板文件傳數據 # context = RequestContext(request, context) # context = {} # 3.模板渲染,產生一個替換后的html內容 res_html = temp.render(context) # 4.返回應答 return HttpResponse(res_html) def index(request): # return render(request, 'booktest/index.html') return my_render(request, 'booktest/index.html')
模板文件加載順序
1)首先去配置的模板目錄下面去找模板文件。
2)去INSTALLED_APPS下面的每個應用的templates去找模板文件,前提是應用中必須有templates文件夾。
# index2頁面未創建 def index2(request): """模板文件的加載順序""" return my_render(request, 'booktest/index2.html')
報錯結果
模板語言
模板語言簡稱為DTL。(Django Template Language)
模板變量
模板變量名是由數字,字母,下划線和點組成的,不能以下划線開頭。
使用模板變量:
{{模板變量名}}
模板變量的解析順序:
例如:{{ book.btitle }}
- 1)首先把book當成一個字典,把btitle當成鍵名,進行取值book['btitle']
- 2)把book當成一個對象,把btitle當成屬性,進行取值book.btitle
- 3)把book當成一個對象,把btitle當成對象的方法,進行取值book.btitle
例如:{{book.0}}
- 1)首先把book當成一個字典,把0當成鍵名,進行取值book[0]
- 2)把book當成一個列表,把0當成下標,進行取值book[0]
如果解析失敗,則產生內容時用空字符串填充模板變量。
使用模板變量時,.前面的可能是一個字典,可能是一個對象,還可能是一個列表。
使用模板變量示例
模板變量函數
def temp_var(request): """模板變量""" my_dict = {"title": "字典鍵值"} my_list = [1, 2, 3] book = models.BookInfo.objects.get(id=1) # 定義模板上下文 context = {'my_dict': my_dict, 'my_list': my_list, 'book': book} return render(request, 'booktest/temp_var.html', context)
模板變量html代碼(booktest/temp_var.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板變量</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> 使用字典屬性:{{ my_dict.title }} <br> 使用列表元素:{{ my_list.1 }} <br> 使用對象屬性:{{ book.btitle }} </body> </html>
模板標簽
模板標簽使用格式:
{% 代碼段 %}
for循環:
{% for x in 列表 %} # 列表不為空時執行 {% empty %} # 列表為空時執行 {% endfor %}
可以通過{{ forloop.counter }}得到for循環遍歷到了第幾次。
if判斷:
{% if 條件 %} {% elif 條件 %} {% else %} {% endif %}
關系比較操作符:> < >= <= == !=
注意:進行比較操作時,比較操作符兩邊必須有空格。
邏輯運算:not and or
django內置標簽與過濾器文檔:內置標簽與過濾器文檔 或者 https://yiyibooks.cn/xx/django_182/ref/templates/builtins.html
模板標簽使用示例
函數
def temp_tags(request): """模板標簽""" books = models.BookInfo.objects.all() return render(request, 'booktest/temp_tags.html', {'books': books})
html代碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板標簽</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .red {background-color: red;} .blue {background-color: blue;} .gray {background-color: gray;} </style> </head> <body> <h1>模板標簽</h1> <ul> {% for book in books %} {% if book.id <= 2 %} <li class="red">{{ forloop.counter }}--{{ book.btitle }}</li> {% elif book.id <= 3 %} <li class="blue">{{ forloop.counter }}--{{ book.btitle }}</li> {% else %} <li class="gray">{{ forloop.counter }}--{{ book.btitle }}</li> {% endif %} {% endfor %} </ul> </body> </html>
過濾器
過濾器其實就是python函數。
過濾器用於對模板變量進行操作。
- date:改變日期的顯示格式。
- length:求長度。字符串,列表.
- default:設置模板變量的默認值。
格式:
模板變量|過濾器:參數
自定義過濾器。
自定義的過濾器函數,至少有一個參數,最多兩個
過濾器的使用示例
過濾器函數
def temp_filter(request): """模板過濾器""" books = models.BookInfo.objects.all() return render(request, 'booktest/temp_filter.html', {'books': books})
過濾器html代碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板過濾器</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .red {background-color: red;} .blue {background-color: blue;} .gray {background-color: gray;} </style> </head> <body> <h1>模板標簽</h1> <ul> {% for book in books %} {% if book.id <= 2 %} <li class="red">{{ book.btitle }}--{{ book.bpub_date|date:'Y-m-d' }}</li> {% else %} {# 加了length后,會將原來的圖書名編程圖書名長度的數字 #} <li class="gray">{{ book.btitle|length }}--{{ book.bpub_date }}</li> {% endif %} {% endfor %} </ul> default過濾器: {# 如果content沒有值,則過濾器會顯示默認的值 #} {{ content|default:"hello" }} </body> </html>
注意:過濾器中,冒號后不能加空格,
例如{{ book.bpub_date|date:'Y-m-d' }}是正確的,而{{ book.bpub_date|date: 'Y-m-d' }}是錯誤的。
否則會報錯,Could not parse the remainder: ': 'Y-m-d'' from 'book.bpub_date|date: 'Y-m-d''
自定義過濾器
自定義過濾器
- 1.在自己的應用下面新建一個 templatetags 文件夾,名字固定;
- 2.在templatetags文件夾下面新建一個py文件,名字自定義,比如filters.py;
- 3.1.在文件中,引入Library類;
- 3.2.創建一個Library類的對象;
- 3.3.定義自己的函數,給函數添加裝飾器@register.filter進行過濾器裝飾;
使用自定義裝飾器
- 1.在需要使用的html文件中導入自定義裝飾器文件,{% load filters %},即 load 文件名;
- 2.使用過濾器;
自定義過濾器示例
import django.template # 創建一個Library類的對象 register = django.template.Library() @register.filter def mod(num): """判斷num是否為偶數""" # 如果傳過來的num是偶數,則返回True,否則返回False return num % 2 == 0
在html代碼中使用模板過濾器

<!DOCTYPE html> <html lang="en"> {% load filters %} <head> <meta charset="UTF-8"> <title>模板過濾器</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .red {background-color: red;} .blue {background-color: blue;} .gray {background-color: gray;} </style> </head> <body> <h1>模板標簽</h1> <ul> {% for book in books %} {% if book.id|mod %} <li class="red">{{ book.id }}--{{ book.btitle }}--{{ book.bpub_date|date:'Y-m-d' }}</li> {% else %} <li class="gray">{{ book.btitle }}--{{ book.bpub_date }}</li> {% endif %} {% endfor %} </ul> </body> </html>
兩個參數的自定義過濾器
自定義過濾器
# 自定義的過濾器,最少有一個參數,最多有兩個參數 # 只有一個參數的話,由|前面的參數傳過來,兩個參數的話,:后面再跟一個參數 # 應注意過濾器參數的前后順序 @register.filter def mod_val(num, val): """判斷num是否能把value整除""" return num % val == 0
html代碼

<!DOCTYPE html> <html lang="en"> {% load filters %} <head> <meta charset="UTF-8"> <title>模板過濾器</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .red {background-color: red;} .blue {background-color: blue;} .gray {background-color: gray;} </style> </head> <body> <h1>模板標簽</h1> <ul> {% for book in books %} {# {% if book.id <= 2 %} #} {# % if book.id|mod %} #} {% if book.id|mod_val:3 %} <li class="red">{{ book.id }}--{{ book.btitle }}--{{ book.bpub_date|date:'Y-m-d' }}</li> {% else %} {# 加了length后,會將原來的圖書名編程圖書名長度的數字 #} <li class="gray">{{ book.btitle|length }}--{{ book.bpub_date }}</li> {% endif %} {% endfor %} </ul> default過濾器: {# 如果content沒有值,則過濾器會顯示默認的值 #} {{ content|default:"hello" }} </body> </html>
模板繼承
模板繼承也是為了重用html頁面內容。
在父模板里可以定義塊,使用標簽:
{% block 塊名 %}
塊中間可以寫內容,也可以不寫
{% endblock 塊名%}
子模板去繼承父模板之后,可以重寫父模板中的某一塊的內容。
繼承格式:
{% extends 父模板文件路徑%} {% block 塊名 %} {{ block.super}} #獲取父模板中塊的默認內容 重寫的內容 {% endblock 塊名%}
模板繼承示例
base/母模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}base模板文件的title{% endblock title %}</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>base模板的header</h1> {% block b1 %} <h2>base模板的block1</h2> {% endblock b1 %} {% block b2 %} <h2>base模板的block1</h2> {% endblock b2 %} <h1>base模板的footer</h1> </body> </html>
child/子模板
{% extends 'booktest/base.html' %} {% block title %}child模板中的title{% endblock title %} {% block b1 %} {{ block.super }} <h2>child模板的block1</h2> {% endblock b1 %} {% block b2 %} <h2>child模板的block2</h2> {% endblock b2 %}
配套函數
def temp_inherit(request): """返回child模板繼承於base的文件""" return render(request, 'booktest/child.html')
在塊里面還可以寫塊,需要注意endblock后面跟 塊名 用以區分哪個塊結束。
html轉義
場景:編輯商品詳情信息,數據表中保存的是html內容。
在模板上下文中的html標記默認是會被轉義的。
小於號< 轉換為< 大於號> 轉換為> 單引號' 轉換為' 雙引號" 轉換為 " 與符號& 轉換為 &
要關閉模板上下文字符串的轉義:可以使用
{{ 模板變量|safe}}
也可以使用:
{% autoescape off %}
模板語言代碼
{% endautoescape %}
模板硬編碼中的字符串默認不會經過轉義,如果需要轉義,那需要手動進行轉義。
safe和autoescape的區別在於,safe只能轉義一個模板變量,而autoescape可以轉義多個變量;
html轉義示例
html_escape.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板轉義</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> html轉義結果:<br> {{ content }}<br> 使用safe過濾器關閉轉義結果:<br> {{ content|safe }}<br> 使用autoescape關閉轉義結果:<br> {% autoescape off %} {{ content }} {{ content }} {% endautoescape %}<br> 模板硬編碼中的字符串默認不會轉義,即會經過html渲染:<br> {{ test|default:'<h1>hello</h1>' }}<br> 手動對硬編碼進行轉義:<br> {{ test|default:'<h1>hello</h1>' }} </body> </html>
配套函數
# /html_escape def html_escape(request): """模板轉義""" return render(request, 'booktest/html_escape.html', {'content': '<h1>hello</h1>'})
驗證碼
在用戶注冊、登錄頁面,為了防止暴力請求,可以加入驗證碼功能,
如果驗證碼錯誤,則不需要繼續處理,可以減輕業務服務器、數據庫服務器的壓力。
自實現驗證碼
安裝pillow
pip install Pillow==3.4.1
編寫函數/視圖

from PIL import Image, ImageDraw, ImageFont from django.utils.six import BytesIO def verify_code(request): # 引入隨機函數模塊 import random # 定義變量,用於畫面的背景色、寬、高 bgcolor = (random.randrange(20, 100), random.randrange( 20, 100), 255) width = 100 height = 25 # 創建畫面對象 im = Image.new('RGB', (width, height), bgcolor) # 創建畫筆對象 draw = ImageDraw.Draw(im) # 調用畫筆的point()函數繪制噪點 for i in range(0, 100): xy = (random.randrange(0, width), random.randrange(0, height)) fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) draw.point(xy, fill=fill) # 定義驗證碼的備選值 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' # 隨機選取4個值作為驗證碼 rand_str = '' for i in range(0, 4): rand_str += str1[random.randrange(0, len(str1))] # 構造字體對象,ubuntu的字體路徑為“/usr/share/fonts/truetype/freefont” font = ImageFont.truetype('FreeMono.ttf', 23) # 構造字體顏色 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) # 繪制4個字 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) # 釋放畫筆 del draw # 存入session,用於做進一步驗證 request.session['verifycode'] = rand_str # 內存文件操作 buf = BytesIO() # 將圖片保存在內存中,文件類型為png im.save(buf, 'png') # 將內存中的圖片數據返回給客戶端,MIME類型為圖片png return HttpResponse(buf.getvalue(), 'image/png')
查看驗證碼
url(r'^verify_code/$', views.verify_code),
在網頁中使用驗證碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/login_check/" method="post"> {% csrf_token %} 用戶:<input type="text" id="username" name="username" value="{{ usernam }}"><br /> 密碼:<input type="password" id="password" name="password"><br /> <input type="checkbox" name="remember">記住用戶名<br /> <img src="/verify_code"> <input type="text" name="vcode"><br> <input type="submit" value="登錄"> </form> </body> </html>
登錄校驗驗證碼函數

def login_check(request): # 1.獲取用戶名和密碼 username = request.POST.get("username") password = request.POST.get("password") remember = request.POST.get("remember") print(username, password) # 獲取用戶輸入的驗證碼 vcode1 = request.POST.get('vcode') # 獲取session中保存的驗證碼 vcode2 = request.session.get('verifycode') # 進行驗證碼校驗 if vcode1 != vcode2: # 驗證碼錯誤 return redirect('/login') # 2.進行校驗 # 3.返回應答 if username == "yifchan" and password == "yifchan": # response = redirect("/index") response = redirect("/change_pwd") # 判斷是否需要記住用戶名 if remember == 'on': # 設置cookie username-過期時間為1周 response.set_cookie('username', username, max_age=7 * 24 * 3600) # 記住用戶登錄狀態 # 只有session中有islogin,就認為用戶已經登錄 request.session['islogin'] = True request.session['username'] = username return response else: return HttpResponse("賬號或密碼錯誤")
url反向解析
當某一個url配置的地址發生變化時,頁面上使用反向解析生成地址的位置不需要發生變化。
根據url 正則表達式的配置動態的生成url。
在項目urls中包含具體應用的urls文件時指定namespace;
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('booktest.urls', namespace='booktest')), ]
在應用的urls中配置是指定name;
urlpatterns = [ url(r'^index/$', views.index, name='index'), url(r'^url_reverse/$', views.url_reverse), # url(r'^show_args/(\d+)/(\d+)$', views.show_args, name='show_args'), # 捕獲位置參數 url(r'^show_kwargs/(?P<c>\d+)/(?P<d>\d+)$', views.show_kwargs, name='show_kwargs'), # 捕獲關鍵字參數 ]
在模板文件中使用時,格式如下:
{% url 'namespace名字:name' %} 例如{% url 'booktest:fan2' %}
帶位置參數:
{% url 'namespace名字:name' 參數 %} 例如{% url 'booktest:fan2' 1 %}
帶關鍵字參數:
{% url 'namespace名字:name' 關鍵字參數 %} 例如{% url 'booktest:fan2' id=1 %}
在視圖中/重定向的時候使用反向解析:
from django.core.urlresolvers import reverse
無參數:
reverse('namespace名字:name名字')
如果有位置參數
reverse('namespace名字:name名字', args = 位置參數元組)
如果有關鍵字參數
reverse('namespace名字:name名字', kwargs=字典)
url反向解析示例
項目下的url文件
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('booktest.urls', namespace='booktest')), ]
應用下的url文件
urlpatterns = [ url(r'^index/$', views.index, name='index'), url(r'^url_reverse/$', views.url_reverse), # url(r'^show_args/(\d+)/(\d+)$', views.show_args, name='show_args'), # 捕獲位置參數 url(r'^show_kwargs/(?P<c>\d+)/(?P<d>\d+)$', views.show_kwargs, name='show_kwargs'), # 捕獲關鍵字參數
url(r'^test_reverse/$', views.test_reverse, name='test_reverse'), # 視圖使用反向解析
]
模板中使用url反向解析
配套函數
def url_reverse(request): return render(request, 'booktest/url_reverse.html') def show_args(request, a, b): return HttpResponse(a+':'+b) def show_kwargs(request, c, d): return HttpResponse(c+':'+d)
url_reverse.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>url反向解析</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> index鏈接:<br> <a href="/index">首頁</a><br> url反向解析生成index鏈接:<br> <a href="{% url 'booktest:index' %}">首頁</a><br> 位置參數 /show_args/1/2:<br> <a href="/show_args/1/2">/show_args/1/2</a><br> 動態生成/show_args/1/2:<br> <a href="{% url 'booktest:show_args' 1 2 %}">/show_args/1/2</a><br> 關鍵字參數 /show_kwargs/3/4:<br> <a href="/show_kwargs/3/4">/show_args/3/4</a><br> 動態生成/show_kwargs/3/4:<br> <a href="{% url 'booktest:show_kwargs' c=3 d=4 %}">/show_args/3/4</a><br> </body> </html>
視圖中使用反向解析
反向解析函數
from django.core.urlresolvers import reverse # url: /test_reverse def test_reverse(request): # 重定向到 /index # return redirect('/index') # url = reverse('booktest:index') # 重定向到位置參數 show_args/1/2 # url = reverse('booktest:show_args', args=(1, 2)) # 重定向到關鍵字參數 show_kwargs/3/4 url = reverse('booktest:show_kwargs', kwargs={'c': 3, 'd': 4}) return redirect(url)
csrf攻擊
首先做一個登錄頁,讓用戶輸入用戶名和密碼進行登錄,登錄成功之后跳轉的修改密碼頁面。在修改密碼頁面輸入新密碼,點擊確認按鈕完成密碼修改。
登錄頁需要一個模板文件login.html.修改密碼頁面也需要一個模板文件change_pwd.html.
顯示登錄頁的視圖login,驗證登錄的視圖login_check,顯示發帖頁的視圖change_pwd,處理修改密碼的視圖change_pwd_action.
加功能:
a)只有用戶登錄之后才可以進行修改密碼操作。
登錄裝飾器函數。
def login_required(view_func): """登錄判斷裝飾器""" def wrapper(request, *args, **kwargs): # 判斷用戶是否登錄 if request.session.has_key('islogin'): # 已經登錄了,就返回到函數 return view_func(request, *args, **kwargs) else: # 未登錄,返回到登錄頁面 return redirect('/login') return wrapper
案例流程圖:
django防止csrf的方式:
- 1) 默認打開csrf中間件。
- 2) 表單post提交數據時加上{% csrf_token %}標簽。
防御原理:
- 1)渲染模板文件時在頁面生成一個名字叫做csrfmiddlewaretoken的隱藏域。
- 2)服務器交給瀏覽器保存一個名字為csrftoken的cookie信息。
- 3)提交表單時,兩個值都會發給服務器,服務器進行比對,如果一樣,則csrf驗證通過,否則失敗。
登錄案例代碼
設計路由
url(r'^login/$', views.login), # 返回登錄頁面 url(r'^login_check/$', views.login_check), # 進行登錄校驗 url(r'^change_pwd/$', views.change_pwd), # 返回修改密碼頁面 url(r'^change_pwd_action/$', views.change_pwd_action), # 修改密碼處理函數
編寫login.html頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/login_check/" method="post"> <label for="username">用戶: <input type="text" id="username" name="username" value="{{ usernam }}"> </label><br /> <label for="password">密碼: <input type="password" id="password" name="password"> </label><br /> <input type="checkbox" name="remember">記住用戶名<br /> <input type="submit" value="登錄"> </form> </body> </html>
編寫login函數

def login(request): """登錄處理函數""" # 判斷用戶是否登錄 if request.session.has_key('islogin'): # return redirect('/index') return redirect('/change_pwd') else: # 獲取cookie username if 'username' in request.COOKIES: username = request.COOKIES['username'] else: username = '' return render(request, "booktest/login.html", {'usernam': username})
編寫

def login_check(request): # 1.獲取用戶名和密碼 username = request.POST.get("username") password = request.POST.get("password") remember = request.POST.get("remember") print(username, password) # 2.進行校驗 # 3.返回應答 if username == "yifchan" and password == "yifchan": # response = redirect("/index") response = redirect("/change_pwd") # 判斷是否需要記住用戶名 if remember == 'on': # 設置cookie username-過期時間為1周 response.set_cookie('username', username, max_age=7*24*3600) # 記住用戶登錄狀態 # 只有session中有islogin,就認為用戶已經登錄 request.session['islogin'] = True request.session['username'] = username return response else: return HttpResponse("賬號或密碼錯誤")
編寫change_pwd.html頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改密碼</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/change_pwd_action"> 新密碼:<input type="password" name="pwd"> <input type="submit" value="確認修改"> </form> </body> </html>
編寫登錄判斷裝飾器

def login_required(view_func): """登錄判斷裝飾器""" def wrapper(request, *args, **kwargs): # 判斷用戶是否登錄 if request.session.has_key('islogin'): # 已經登錄了,就返回到函數 return view_func(request, *args, **kwargs) else: # 未登錄,返回到登錄頁面 return redirect('/login') return wrapper
定義change_pwd函數

@login_required def change_pwd(request): """顯示修改密碼頁面""" return render(request, 'booktest/change_pwd.html')
定義change_pwd_action函數

@login_required def change_pwd_action(request): """模擬修改密碼處理""" # 1.獲取新密碼 pwd = request.POST.get("pwd") # username = request.COOKIES['username'] username = request.session.get('username') # 2.實際開發的時候,修改對應的數據庫中的數據 # 3.返回應答 return HttpResponse('%s修改密碼為:%s' % (username, pwd))
csrf偽造
django默認開啟csrf防護,並且只針對post提交;
- 1.開啟csrf防護,把注釋的settings文件里面的csrf放開注釋;
- 2.在要提交表單的地方,添加{% csrf_token %}
csrf防護示例代碼
login頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/login_check/" method="post"> {% csrf_token %} 用戶:<input type="text" id="username" name="username" value="{{ usernam }}"><br /> 密碼:<input type="password" id="password" name="password"><br /> <input type="checkbox" name="remember">記住用戶名<br /> <input type="submit" value="登錄"> </form> </body> </html>
change_pwd頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改密碼</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/change_pwd_action/" method="post"> {% csrf_token %} 新密碼:<input type="password" name="pwd"> <input type="submit" value="確認修改"> </form> </body> </html>
在模擬的時候,自制的第三方網站,可以拿到自己頁面的csrftoken隱藏域的信息,然后放到自己的第三方網站代碼去;
但在實際上,這樣很難實現。