Django之请求和响应
1.請求和響應概述
Django中的請求實際就是視圖函數(shù)view中的第一個參數(shù),就是固定為request,其為HttpRquest對象,Django接收到http請求后,會根據(jù)請求數(shù)據(jù)創(chuàng)建HttpRequest對象,該對象涵蓋了很多包括屬性,其涵蓋了請求的相關信息。這里介紹幾個常用的屬性:- path_info:URL字符串
- method:請求方法,比如‘GET’和‘POST’方法等
- GET:QueryDict查詢字典的對象,包含get請求方法的所有數(shù)據(jù)
- POST:QueryDict查詢字典的對象,包含post請求方法的所有數(shù)據(jù)
- FILES:類似字典的對象,包含所有的上傳文件的信息
這里在urls中新增test_req路由
path('test_req',views.test_request)在視圖函數(shù)中新增一個test_request函數(shù)
def rest_request(request):print('path info is:',request.path_info)print('method is :',request.method)print('request.GET is :', request.GET)return HttpResponse("test is ok")運行工程,并在終端進行查看
Django響應中,經(jīng)常使用的是HttpResponse函數(shù),其參數(shù)調(diào)用格式如下
HttpResponse(content=響應體,contenttype=響應體數(shù)據(jù)類型,status=狀態(tài)碼)
常見的contentType有:
text/html 默認的html
text/plain 純文本
text/css css 文件
text/javascript js文件
multipart/form-data 文件提取
application/json json傳輸
application/xml xml文件
2.GET和POST請求
無論是GET還是POST請求,統(tǒng)一都是由視圖函數(shù)接收,通過判斷request.method區(qū)分是哪種方法,代碼一般為
if request.method == 'GET':處理get請求的邏輯 elif request.method =='POST':處理post請求的邏輯 else:其他處理邏輯創(chuàng)建一個mysite2的工程,如何創(chuàng)建工程參考 Django之url和視圖函數(shù),在mysite2同名文件下的urls.py的urlpatterns新增路由
# http:127.0.0.1:8000/test_get_postpath('test_get_post',views.test_get_post),在mysite2同名文件下的views.py中定義函數(shù)test_get_post
def test_get_post(request):if request.method == 'GET':passelif request.method == "POST":passelse:passreturn HttpResponse('--test get post is ok-- ')因此get和post請求的總體框架如上所示,接著詳細介紹下
2.1 GET請求
GET請求動作,一般用于向瀏覽器獲取/查詢數(shù)據(jù),能夠產(chǎn)生GET請求的場景有:
- 瀏覽器地址欄輸入url,點擊回車
- < a href=“地址?key1=value1&key2=value2”>
- form表單中的method方法為GET
如果是GET請求方式,可以給服務端傳遞數(shù)據(jù),通過使用查詢字符串(Query String),由于是明文傳遞,因此切忌不要傳遞敏感數(shù)據(jù)
使用查詢字符串傳遞數(shù)據(jù)的時候,可以使用如下方法獲取請求對象的屬性
request.GET['參數(shù)名'] request.GET.get('參數(shù)名','默認值') request.GET.getlist('參數(shù)名')在mysite2的同名文件夾下的urls.py的url_pattern中新增
path('test_get_post',views.test_get_post),再視圖函數(shù)views.py中定義視圖函數(shù)test_get_post
def test_get_post(request):if request.method == 'GET':print(request.GET)print(request.GET['a'])print(request.GET.get('c','there is no c'))print(request.GET.getlist('a'))elif request.method == "POST":passelse:passreturn HttpResponse('--test get post is ok-- ')運行python mange.py runserver
在終端處查看如下結果
這里注意到,查詢字符串中輸入的是?a=100&a=200&a=400,使用request.GET[‘a(chǎn)’]輸出的是最后一個a
2.2 POST請求
POST請求,一般用于向服務器提交數(shù)據(jù),客戶端通過表單等POST請求將數(shù)據(jù)傳遞給服務器,其格式如:
<form method='post' action='login'>姓名:<input type=text name='username><input type='submit' value='登錄> </form>服務端在views.py中,通過request.method進行判斷
request.method == "POST":使用post方法傳遞數(shù)據(jù)的時候,可以使用如下方法獲取請求對象的屬性
request.POST['參數(shù)名'] request.POST.get('參數(shù)名','默認值') request.POST.getlist('參數(shù)名')注意這里在settings.py中的MIDDLEWARE中取消csrf驗證,否則Post提交會提示csrf 403的報錯
MIDDLEWARE = [...# 'django.middleware.csrf.CsrfViewMiddleware',...在views.py新增變量
POST_FORM = ''' <form method = 'post' action = '/test_get_post'>用戶名:<input type = 'text' name = 'uname'><input type='submit' value='提交'> </form> ''' def test_get_post(request):if request.method == 'GET':print(request.GET)print(request.GET['a'])print(request.GET.get('c','there is no c'))print(request.GET.getlist('a'))return HttpResponse(POST_FORM)elif request.method == "POST":request.POST.get['uname']return HttpResponse('post is ok')else:passreturn HttpResponse('--test get post is ok-- ')輸入http:127.0.0.1:80000?a=40
3.模板層
Django中的是MTV模式,Model-Template-View
模板是可以根據(jù)字典數(shù)據(jù)動態(tài)變化的Html頁面。模板可以根據(jù)視圖中傳遞的字典數(shù)據(jù)動態(tài)的生成相應的Html網(wǎng)頁
3.1 模板配置
創(chuàng)建模板文件夾<項目名>/templates,即在mysite項目問價下創(chuàng)建templates普通文件夾。
在setttings.py中TEMPPLATES配置項中,做如下配置:
1.BACKEND:指定模板引擎
2.DIRS:模板的搜索目錄
3.APP_DIRS:是否要在應用的templates文件夾搜索模板文件
4.OPPTIONS:有關模板的選項
配置項目中,需要做如下修改:
3.2模板加載
之前我們都是使用return HttpResposne加載返回一個字符串對象,實際開發(fā)的時候,很少會直接返回一個HttpResponse對象,這里創(chuàng)建了模板并使用模板,那如何進行加載模板,主要有以下兩種方式: 方式一: 通過loader獲取模板,通過HttpResponse進行相應,在視圖函數(shù)中一般處理為: from django.template import loader #1.通過loader加載模板 t = loader.get_template('模板文件名') #2.將t裝換成HTML字符串 html = t.render(字典數(shù)據(jù)) #3.用響應對象將轉(zhuǎn)換的字符串內(nèi)容返回給瀏覽器 return HttpResponse(html)因此這里配置好setttings.py中的TEMPLATES .DIRS后,在url_patterns中新增一個路由
path('test_html',views.test_html),在文件夾templates下新建一個test_html.html文件
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>模板層</title> </head> <body> <p>是模板層輸出</p> </body> </html>接著在視圖函數(shù)中新增一個test_html函數(shù)
from django.template import loader def test_html(reqeust):t = loader.get_template('test_html.html')html = t.render()return HttpResponse(html)再次刷新界面,展示如下所示
方式二:
使用render()直接加載并響應模板,在視圖函數(shù)中:
這里既然render提到了字典數(shù)據(jù),那視圖層與模板層之間的數(shù)據(jù)如何交互呢?
1.視圖函數(shù)中可以Python變量封裝到字典中傳遞到模板
2.模板中,可以使用{{ 變量名 }}的語法,調(diào)用視圖傳遞進來的變量,這里的變量名就是字典中的key1,key2…
將視圖函數(shù)views.py中的方案2修改如下:
接著修改test_html.html文件
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>模板層</title> </head> <body> <p>客戶為{{ username }}年齡為{{ age }}的模板層展示 </p> </body> </html>結果展示為:
3.3 模板層變量
在3.2中已經(jīng)使用了模板的變量,在視圖函數(shù)view中,使用字典傳遞參數(shù),那可以給模板傳遞哪些數(shù)據(jù)類型呢?
-
str 字符串 int 整形
-
list 列表 tuple 元組
-
dict 字典 func 方法
-
obj 類實例化的對象
對應的在模板中使用變量的語法如下所示: -
{{ 變量名 }}
-
{{ 變量名.index }}
-
{{ 變量名.key }}
-
{{ 對象.方法名 }}
-
{{ 函數(shù)名 }}
接著上面的示例,在urls.py中新增一個路由
新增一個模板為test_html_param.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><h3>int 是 {{ int }}</h3> <h3>str 是 {{ str }}</h3> <h3>lst 是 {{ lst }}</h3> <h3>lst 是 {{ lst.0 }}</h3> <h3>dict 是 {{ dict.a }}</h3> <h3>dict['a'] 是 {{ dict }}</h3> <h3>functions 是 {{ func }}</h3> <h3>class_obj 是 {{ class_obj.say }}</h3></body> </html>在視圖函數(shù)中,新增test_html_view函數(shù)
def test_html_param(request):dic = {}dic['int'] = 88dic['str'] = 'django'dic['lst'] = ['tom','jack','Liky']dic['dict'] = {'a':9,'b':10}dic['func'] = say_hidic['class_obj'] = Dog()return render(request,'test_html_param.html',dic) def say_hi():return 'hello' class Dog:def say(self):return "Dog"輸出結果如下所示:
3.4 模板標簽
將一些服務器端的功能嵌入到模板中,例如流程控制。標簽的語法是
{% 標簽 %} ... {% 結束標簽 %}if標簽
{% if 條件表達式1 %} ... {% elif 條件表達式2 %} ... {% else %} ... {% endif %}這里針對標簽,舉例如下所示:
在urls.py中新增一個路由
在templates下新增一個mycal.html文件
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>計算器</title> </head> <body><form action="/mycal" method="post"><input type="text" name="x" value="{{ x }}"><select name="op"><option value="add">+加</option><option value="sub">-減</option><option value="mul">*乘</option><option value="div">+/除</option></select><input type="text" name="y" value="{{ y }}"> = <span>{{ result }}</span><div><input type="submit" value="開始計算"></div> </form> </body> </html>視圖函數(shù)views.py中新增
def test_mycal(request):if request.method == "GET":return render(request,"mycal.html")elif request.method == "POST":# 處理計算x = request.POST['x']y = request.POST['y']op = request.POST['op']result = 0x,y = int(x),int(y)if op == 'add':result = x + yelif op == 'mul':result = x * yelif op == 'sub':result = x - yelif op == 'dic':result = x / yelse:pass# 還要能展示用戶上次選擇的和填寫數(shù)據(jù)return render(request,'mycal.html',locals())
運行中發(fā)現(xiàn)一個問題,每次選擇的運算符號之后,運算之后,運算符號都會停留在+加號,這里沒喲記錄
了解到select中有一個屬性為selected,如果某個選項設置了selected屬性,則會把其作為第一項進行顯示。結合這個屬性,對mycal.html做如下調(diào)整
另一個常用的標簽是for標簽
{% for 變量 in 可迭代對象 %}...循環(huán)語句 {% empty %}...可迭代對象無數(shù)據(jù)是填充的語句 {% endfor %}3.5 模板層繼承
繼承的思想在面向?qū)ο缶幊讨谐3S畜w現(xiàn),在目標層也可以利用這樣的思想,從而事項模板層的代碼復用。
我們村查看豆瓣電影中的界面,看看所謂模板繼承的原理。
點擊選電影和,電視劇發(fā)現(xiàn)界面布局完全一樣,唯一不同的就是中間部分展示的內(nèi)容有所不同。類似如下風格:
模板繼承可以使用父模板的內(nèi)容,子模板直接繼承父模板的全部內(nèi)容并可以覆蓋父模板中的相應的塊。語法如下所示:
- 定義父模板中的block標簽
- 標識出哪些在子模板中是允許被修改的
- block標簽,在父模板中定義,可以在子模板中覆蓋
定義子模板可以如下操作
- 繼承模板 extends標簽,寫在模板文件的第一行。如{% extends 'base.html %}
- 子模板 重寫父模板中的內(nèi)容塊
這里舉例說明
在路由urls.py中新增如下路由
在視圖函數(shù)views.py中新增
def base_view(request):return render(request,'base.html') def music_view(request):return render(request, 'music.html') def sport_view(request):return render(request, 'sport.html')在templates文件夾下新增base.html文件
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8">{% block mytitle %}<title>主頁</title>{% endblock %} </head> <body> <a href="/music_index">音樂頻道</a> <a href="/sport_index">體育頻道</a> </br>{% block info %}這是主頁 {% endblock %}</br><h3>有問題,請聯(lián)系123456xxxx</h3> </body> </html>由于前文提到父模板可以繼承的部分就是在父模板中使用block標注出來的部分,在子模板中extends之后并重寫該部分,新增music.html和sport.html
{% extends 'base.html' %}{% block mytitle %}<title>音樂頻道</title> {% endblock %}{% block info %}歡迎來到音樂頻道 {% endblock %}運行之后如下所示:
項目整體結構如下所示
4.url反向解析
url在代碼中一般出現(xiàn)在如下兩個地方:
url反向解析,指在視圖或者模板中,用Path定義的名稱動態(tài)查找或計算出相應的路由。path語法為:
4.1 url反向解析-模板
url反向解析在模板中-通過url標簽實現(xiàn)地址的反向解析
{% url '別名' %} {% url '別名' '參數(shù)值1' '參數(shù)值2' %} #url中參數(shù)一律使用字符串傳參 eg: {% url 'pagen' '400' %} {% 'person' age='18' name='django' %}在urls.py下新增兩個路由
# http://127.0.0.1:8000/test/urlpath('test/url',views.test_url),path('test_url_result_display',views.test_url_result_display,name='turs'),這里的url很長,我們需要做個簡短的別名進行處理,設置別名為turs新增視圖函數(shù)views.py下的處理函數(shù)
def test_url(request):return render(request,'test_url.html') def test_url_result_display(request):return HttpResponse('--test url result is ok--')templates模板下新增一個模板,test_url.html文件
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>測試url</title> </head> <br> <a href="http://127.0.0.1:8000/test_url_result_display">絕對地址</a> <a href="/test_url_result_display">相對地址</a></br> <a href="{% url 'turs' %}">url反向解析</a> </body> </html>那攜帶參數(shù)的url反向解析如何實現(xiàn)呢?
新增一個path路由
視圖函數(shù)變更,新增一個參數(shù)用于接收
def test_url_result_display(request,pageNumber):return HttpResponse('--test url result is ok--')模板中
<a href="{% url 'turs' '100' %}">url反向解析帶參數(shù)</a>結果如下所示:
url反向解析,還有很重要的一個功能,比如上文中定義的path變化了,將
發(fā)現(xiàn)其他的幾個都不能訪問了,但是反向解析的版本仍然可以使用,這就是url “動態(tài)的”綁定。
4.2 url反向解析-視圖
上面介紹了url反向解析在模板中如何使用,現(xiàn)在介紹下url反向解析如何在視圖函數(shù)中使用。
from django.url import reverse reverse('別名',args[],kwargs=[]) ex: print(reverse('pagen',args=[300])) print(reverse('person',kwargs={'name':'django','age':20}))繼續(xù)上面的介紹,給url_pattern做如下修改
path('test/url',views.test_url,name='tu'),視圖函數(shù)做如下修改
def test_url_result_display(request,pageNumber):# return HttpResponse('--test url result is ok--')# 跳轉(zhuǎn)302from django.urls import reverseurl = reverse('tu')return HttpResponse(url)進入之后,點擊跳轉(zhuǎn)成功,這里瀏覽器是如何得知,跳轉(zhuǎn)的位置,通過Loaction進行定位
上一篇:Django之url和視圖函數(shù)
總結
以上是生活随笔為你收集整理的Django之请求和响应的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django之url和视图函数
- 下一篇: Django之静态文件