1. 程式人生 > 其它 >Django學習記錄

Django學習記錄

一、專案建立

1、使用pycharm建立Django專案

 

 會建立一個跟專案同名的app,在該app中可以設定整個專案主路由、配置資訊等

 

 2、在pycharm 終端使用python3 manage.py 操作django專案。如 python3 manage.py runserver啟動django專案(截圖中的提示表示沒有同步資料庫資訊)

 

二、URL

Django處理URL請求

瀏覽器位址列 -> http://127.0.0.1:8000/admin

1、Django 從配置檔案中根據ROOT_URLCONF找到主路由檔案;預設情況下,該檔案是專案同名app下的urls.py

2、Django 載入主路由檔案中的urlpatterns變數(包含很多路由的陣列)

3、依次匹配urlpatterns中的path,若匹配到第一個合適的路勁,則會中斷後續匹配

4、匹配成功->呼叫對應的師徒函式處理請求,返回響應

5、匹配失敗-> 返回404

主路由 urls.py 示例
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

  

三、檢視函式 

定義:檢視函式是用於接收一個瀏覽器請求(httprequest物件)並通過httpresponse物件返回響應的函式。

語法:

def xxx_view(request):
    pass
    return HttpResponse物件

ps:第一個引數必須是request
返回值必須是HttpResponse物件

示例:

1、在與專案同名的app下新建urls.py檔案

2、建立檢視函式 page_1_view

from django.http import HttpResponse

def
page_1_view(request): html = "<h1>test1</h1>" return HttpResponse(html)

3、在主路由中新增路徑及對應檢視函式

from django.urls import path
from . import views # 在當前目錄引用

urlpatterns = [
    path('admin/', admin.site.urls),
    path('page/1', views.page_1_view) #配置路由和檢視函式
]

 

 

 path函式詳解:

1、匯入  from django.urls import path

2、語法 path(route, views, name=None)

3、引數 route: 字串型別,匹配請求的路徑。

            views:指定路徑對應的檢視處理函式名稱。(views不能新增括號,新增括號之後就是將函式的結果引用過來了,兩者完全不同

    name:為地址起的別名,在模板中地址反向解析時使用

 

四、path轉換器 

語法: <轉換器型別:自定義名稱>

作用:若轉換器型別匹配到對應型別的資料,則將資料按照關鍵字傳參的方式傳給檢視函式

例:   path('update/<int:note_id>', views.update_note)

轉換器型別及作用:

轉換器型別 作用 示例

str

匹配除'/'之外的非空字串 'user/<str:username>'匹配'user/wx'
int 匹配0或者任何整數,返回一個int 'page/<int:page>'匹配'page/1'
slug 匹配任意由ascll字母或數字以及連字元和下劃線組成的短標籤 'detail/<slug:sl>'匹配'detail/test-django'
path 匹配非空欄位,包括路徑分隔符'/' 'test/<path:pa>'匹配'test/a/b/c'

示例:

views.py
def page_view(request):
      html = f"這是編號為{str(pg)}"的頁面
      return HttpResponse(html)
  
urls.py

path('page/<int:pg>', views.page_view)

 

 ps: urls.py中的urlpatterns按從上往下的順序匹配

五、re_path()

定義:在url的匹配中可以使用正則表示式進行精確匹配

語法:re_path(reg, view, name=xxx)

         正則表示式為命名分組模式(?P<name>pattern); 匹配提取引數後用關鍵字傳參方式傳遞給檢視函式

示例:

from django.urls import path, re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^(?P<x>\d{1,2})/(?P<y>\w+)/(?P<z>\d{1,2})$', views.page_view())
]
^ 代表開頭
& 代表結束
P 代表正則匹配
<x> 代表我們給他命名為x
\d 匹配數字
{1,2} 匹配1-2位
\w+ 匹配字串

六、請求和響應

Django主要做的是網頁,而請求和響應是網頁十分重要的東西。

請求:指瀏覽器通過http協議傳送給服務端的資料

響應:指服務收到請求後做出響應處理後再回復給瀏覽器的資料。

 

請求方式:

1、根據http標準,http請求可以使用多種請求方法。

2、http1.0定義了三種請求方發:get、post、head(最常用)。

3、http1.1新增了五種請求方法:options、put、delete、trace、connect。

序號 方法 描述
1 GET 請求指定的頁面資訊,並返回實體主體
2 HEAD 類似於get方法,只是返回的資料中沒有具體的內容,用於獲取報頭
3 POST 向指定資源提交資料進行處理請求(例如提交表單或上傳檔案),資料被包含在請求中,post請求可能導致新的資源建立或已有的資源修改
4 PUT 從客戶端向服務端傳送的資料取代指定的文件中的內容
5 DELETE 請求伺服器刪除指定的頁面
6 CONNECT http1.1協議中預留給能夠將連線改為管道方式的代理伺服器
7 OPTIONS 允許客戶端檢視伺服器的效能
8 TRACE 回顯伺服器收到的請求,主要用於測試或診斷

 

Django中的請求:

1、請求在Django中是檢視函式的第一個引數,即HttpRequest物件。

2、Django接收到http協議的請求後,會根據請求資料報文建立HttpRequest物件。

3、HttpRequest物件通過屬性描述了請求的所有相關資訊。

 

Django中請求的屬性:

1、path_info:URL字串。

2、method:標識http請求的方法。

3、GET:QueryDict查詢字典的物件,包含get請求方法的所有資料。

4、POST:QueryDict查詢字典的物件,包含post請求方法的所有資料。

5、FILES:類似於字典的物件,包含所有上傳的檔案資訊。

6、COOKIES:python字典,包含所有的cookie,key和value都是字串。

7、session:類似字典的物件,表示當前的會話。

8、body:字串,請求體的內容。

9、scheme:請求協議(http/https).

10、get_full_path():請求的完整路徑。

11、META:請求中的元資料。 META['EMOTE_ADDR']:客戶端IP地址。

 

 

響應狀態碼:

200 請求成功
301 永久重定向
302 臨時重定向
404 請求的資源不存在
500 伺服器錯誤

響應狀態碼分類:

HTTP狀態碼由三位十進位制數字組成,第一個十進位制數字定義了狀態碼的型別,後兩個數字沒有分類的作用。

分類 分類描述
1** 資訊。伺服器收到資訊,需要請求者繼續執行操作
2** 成功。操作被成功接受並處理
3** 重定向。需要進一步的操作以完成請求
4** 客戶端錯誤。請求包含語法錯誤或無法完成的請求
5** 服務端錯誤。服務端在處理請求的過程中發生錯誤

 

Django響應:

  建構函式格式:

  HttpResponse(content=響應體,content_type=響應體資料型別,status=狀態碼) 

  作用:

  向瀏覽器返回響應,同時攜帶響應體內容

 

常用的Content-Type:

'text/html' 預設的,html檔案
'text/plain' 純文字
'text/css' css檔案
'text/javascript' js檔案
'multipart/rom-data' 檔案提交
'application/json' json傳輸
'application/xml' xml檔案

 

 HttpResponse子類:

型別

作用 狀態碼

HttpResponseRedirect

重定向 302
HttpResponseNotModified 未修改 304
HttpResponseBadRequest 錯誤請求 400
HttpResponseNotFound 沒有對應的資源 404
HttpResponseForbidden 請求被禁止 403
HttpResponseServerError 伺服器錯誤 500

 

 

七、GET和POST請求

GET和POST請求:

  無論是GET還是POST,統一由檢視函式接收請求,通過request.methed區分具體的請求操作。

示例:

def test_get_post(request):
    
    if request.method == 'GET':
        pass
    elif request.method == 'POST':
        pass
    else:
        pass
    return HttpResponse('--test get post is ok--')

 

GET處理:

1、GET請求動作,一般用於向伺服器獲取資料

2、能夠產生GET請求的場景:

  -瀏覽器位址列中輸入URL後,回車

  -<a href='地址?引數=值&引數=值'>

  -form表單中的methed為get

3、GET請求中如果有資料需要傳遞給伺服器,通常會用查詢字串(Query String)傳遞。【不要傳遞敏感資料】

  -URL格式:xxx?引數名1=值1&引數名2=值2

  -如:http://127.0.0.1/page?a=1&b=2

  -服務端接收引數。獲取客戶端GET請求的資料

方法示例:
request.GET['引數名']  #QueryDict
request.GET.get('引數名','預設值')
request.GET.getlist('引數名')

views.py

def test_get_post(request):
    if request.method == 'GET':
        print(request.GET['a'])
        print(request.GET.get('c', 'no c'))
        print(request.GET.getlist('a'))
    elif request.method == 'POST':
        pass
    else:
        pass
    return HttpResponse('--test get post is ok--')

urls.py
path('test_get_post',views.test_get_post),

 

 

POST處理:

1、post請求動作,一般用於向伺服器提交大量/隱私資料

2、客戶端通過表單等POST請求將資料傳遞給伺服器,如:

<form methed='post' action="/login">
    姓名: <input type="text" name="username">
    <input type="submit" value="登入">
</form> 

3、服務端接收引數:

  -通過request.methed來判斷是否為post請求,如:

if request.methed =='POST':
    處理post請求的資料並響應
else:
    處理非post請求

4、取消csrf驗證,否則Django會拒絕服務端發來的POST請求,返回403

5、使用POST方法接收客戶端資料 

request.POST['引數名'] #QueryDict
request.POST.get('引數名', '')
request.POST.getlist('引數名')

八、Django設計模式及模板層

MTV

MTV代表Model-Template-View(模型-模板-檢視) 

M 模型層(Model): 負責與資料庫互動

T 模板層(Template):  負責呈現內容到瀏覽器(HOW)

V 檢視層(View):  負責接收請求、獲取資料、返回結果(WHAT)

 

模板層

1、定義

  模板是可以根據字典資料動態變化的html網頁

  模板可以根據檢視中傳遞的字典資料動態生成相應的html網頁

2、模板配置

 建立模板資料夾 <專案名>/templates

 在settings.py中TEMPLATES配置項

  BACKEND: 指定模板的引擎

  DIRS: 模板的搜尋目錄(可以是一個也可以是多個)

  APP_DIRS: 是否要在應用的templates資料夾中搜索模板檔案

  OPTIONS: 有關模板的選項

 

 

 3、模板的載入方式

方式一:通過loader獲取模板,通過HttpResponse進行響應

在檢視函式中:

from django.template import loader
# 1、通過loader載入模板
t = loader.get_template('模板檔名')
# 2、將t轉換成HTML字串
html = t.render('字典資料')
# 3、用響應物件將返回的字串內容返回給瀏覽器
return HttpResponse(html)

views.py

def test_html(request):

    from django.template import loader

    t = loader.get_template('test_html.html')
    html = t.render()
    return HttpResponse(html)

urls.py

path('test_html',views.test_html)

test_html.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>來自模板層</h3>
</body>
</html>

執行結果如下圖:

 

 

 

方式二: 使用render()直接載入並響應模板

在檢視函式中:

from django.shortcuts import render
return render(request, '模板檔名', '字典資料')

views.py

def test_html(request):

    # from django.template import loader
    #
    # t = loader.get_template('test_html.html')
    # html = t.render()
    # return HttpResponse(html)
    from django.shortcuts import render
    return render(request, 'test_html.html')

執行結果如下圖:

 

 4、檢視層與模板層之間的互動

  檢視函式中可以將python變數封裝到字典中傳遞給模板

def xxx_view(request):
    dic = {
         "變數1": "值1",
         "變數2": "值2"
    }    
    return render(request, 'xxx.html', dic)

  在模板中可以使用{{變數名}}呼叫檢視函式傳來的變數

views.py

def test_html(request):
    # from django.template import loader
    #
    # t = loader.get_template('test_html.html')
    # html = t.render()
    # return HttpResponse(html)
    from django.shortcuts import render
    dic = {'name': 'tester', 'age': '17'}
    return render(request, 'test_html.html', dic)

test_html.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>{{name}}來自模板層<h3>
</body>
</html> 

執行結果如下圖:

 

 

 5、能從檢視傳遞到模板中的資料型別

str -字串    int -整型
list -陣列     tuple -元組
dict -字典     func -方法
object -類例項化的物件

模板中使用變數的語法:
{{變數名}}

{{變數名.index}}

{{變數名.key}}

{{物件.方法}}

{{函式名}}

views.py

def test_html_param(request):
    dic = {}
    dic['int'] = 88
    dic['str'] = 'zhangsan'
    dic['lst'] = ['Tom', 'Jack', 'Lily']
    dic['dict'] = {'a': 9, 'b': 8}
    dic['func'] = say_hi
    dic['class_obj'] = Test()

    return render(request, 'test_html_param.html', dic)


def say_hi():
    return 'hahha'


class Test:
    def say(self):
        return 'tester'

urls.py

path('test_html_param',views.test_html_param),

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 }}</h3>
    <h3>dict['a'] 是 {{ dict.a }}</h3>
    <h3>function 是 {{ func }}</h3>
    <h3>class_obj 是 {{ class_obj.say }}</h3>
</body>
</html> 

執行結果如下圖:

 

 6、模板中的標籤

作用:將一些服務端的功能嵌入到模板中,例如流程控制等。

標籤語法:

{%標籤%}
......
{%結束標籤%} 

if 標籤

語法:

{% if 條件表示式1 %}
...
{% elif 條件表示式2 %}
...
{% elif 條件表示式3 %}
...
{% else 條件表示式4 %}
...
{% endif %}

注意:

  if條件表示式裡可以用的運算子 ==, !=, >, <, >=, <=, in, not in, is, is not, not, and, or

  在if標記中使用實際括號是無效的語法,如果需要指定他們的優先順序,應使用巢狀的if標記

示例:

views.py

def test_if_for(request):
    dic = {}
    dic['x'] = 10
    return render(request,'test_if_for.html',dic)

urls.py

path('test_if_for',views.test_if_for),

test_if_for.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試 if和for</title>
</head>
<body>
    {% if x > 10 %}
        今天天氣很好
    {% else %}
        今天天氣非常好
    {% endif %}
</body>
</html>

  

for 標籤

語法:

{% for 變數 in 可迭代物件%}
    ...迴圈語句
{% empty %}
    ...可迭代物件無資料時填充的資料
{% endfor %}

  

內建變數:

變數 描述
forloop.counter 迴圈的當前迭代(從1開始索引)
forloop.counter0 迴圈的當前迭代(從0開始索引)
forloop.revcounter counter值的倒序
forloop.revcounter0 revcounter值的倒序
forloop.first 如果這是第一次通過迴圈,則為真
forloop.last 如果這是最後一次迴圈,則為真
forloop.parentloop 當巢狀迴圈,parentloop表示外層迴圈

示例:

views.py

def test_if_for(request):
    dic = {}
    dic['x'] = 10
    dic['lst'] = {'Tom', 'Jack', 'Lily'}
    return render(request,'test_if_for.html',dic)

test_if_for.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試 if和for</title>
</head>
<body>
    {% if x > 10 %}
        今天天氣很好
    {% else %}
        今天天氣非常好
    {% endif %}
    <br>
    {% for name in lst %}
        {% if forloop.first %} $$$$${% endif %} <!--當第一次迴圈的時候會輸出該符號-->
        <p>{{ forloop.counter }} {{ name }}</p> <!--forloop.counter 從1開始計數-->
        {% if forloop.last %} ===={% endif %}<!--當第最後一次迴圈的時候會輸出該符號-->
    {% empty %}
        當前無資料
    {% endfor %}
</body>
</html>
</body>
</html>

執行結果如下圖: