Django進階篇

閱讀目錄:css

1、Django框架html

 1.MVC框架python

  MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯彙集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。具備耦合性低、重用性高、生命週期成本低等優勢。mysql

 

 

2.Django的MTV框架jquery

  Django框架的設計模式借鑑了MVC框架的思想,也是分紅三部分,來下降各個部分之間的耦合性。不一樣之處在於它拆分的三部分爲:Model(模型)、Template(模板)和View(視圖),也就是MTV框架。git

Model(模型):負責業務對象與數據庫的對象(ORM)ajax

       Template(模版):負責如何把頁面展現給用戶正則表達式

       View(視圖):負責業務邏輯,並在適當的時候調用Model和Templatesql

此外,Django還有一個urls分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Template數據庫

 

2、Django模板(Template)系統

 1.經常使用用法

兩種特殊符號:

(1)變量相關使用 {{ }}

(2)邏輯相關使用 {%  %}

2.變量

在Django的模板語言中按此語法使用:{{ 變量名 }}。

當模版引擎遇到一個變量,它將計算這個變量,而後用結果替換掉它自己。 變量的命名包括任何字母數字以及下劃線 ("_")的組合。 變量名稱中不能有空格或標點符號。

點(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的順序查詢:

字典查詢(Dictionary lookup)
屬性或方法查詢(Attribute or method lookup)
數字索引查詢(Numeric index lookup)

{# 取l中的第一個參數 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取對象的name屬性 #}
{{ person_list.0.name }}
{# .操做只能調用不帶參數的方法 #}
{{ person_list.0.dream }}

  

 1 def test(request):
 2     content1 = ['列表值1', '列表值2', {'id': '10024087', 'name': 'felix'}]
 3     content2 = {'id': '10024087', 'name': 'felix', 'age': 18, 'items': 123}
 4     content3 = [['列表值1', '列表值2', '10024087', 'felix'], ['列表值1', '列表值2', '10024087', 'felix']]
 5     p1 = Person('felix', 18)
 6     p2 = Person('new', 16)
 7     p_list = [p1, p2]
 8     import datetime
 9     now = datetime.datetime.now()
10     link = '''<a href="http://www.baidu.com">百度</a>'''
11     script = "<script>for (i=0;i<100;i++) {alert(123);}</script>"
12     p_text = '''
13 
14     若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
15     參數:截斷的字符數
16     {{ value|truncatechars:9}}'''
17     if request.method == 'GET':
18         return render(
19             request,
20             'test.html',
21             {
22                 'data_str': '字符串值',
23                 'data_tuple': ('元組值1', '元組值2'),
24                 'data_list': content1,
25                 'data_dict': content2,
26                 'data': [
27                     {'id': '10024087', 'name': 'felix', 'age': 18},
28                     {'id': '10024088', 'name': 'alina', 'age': 19},
29                     {'id': '10024089', 'name': 'allen', 'age': 20}
30                 ],
31                 'person': p1,
32                 'p_list': p_list,
33                 'size': 102400000,
34                 'now': now,
35                 'link': link,
36                 'script': script,
37                 'p_text': p_text,
38                 'a': 100,
39                 'b': 10,
40                 'c': 1,
41                 'content3': content3
42 
43             })
44     if request.method == 'POST':  # 獲取對象
45         file = request.FILES.get('file')
46         print(file.chunks)
47         img_dir = os.path.join(BASE_DIR, 'static', 'file', file.name)
48         print(img_dir)
49         with open(os.path.join(BASE_DIR, 'static', 'file', file.name), 'wb') as f:
50             for chunk in file.chunks():
51                 f.write(chunk)
52             # return HttpResponse('上傳文件成功!')
53             # return render(request,'test.html',{'msg':'上傳文件成功!'})
54             return render(
55                 request,
56                 'test.html',
57                 {
58                     'data_str': '字符串值',
59                     'data_tuple': ('元組值1', '元組值2'),
60                     'data_list': content1,
61                     'data_dict': content2,
62                     'data': [
63                         {'id': '10024087', 'name': 'felix', 'age': 18},
64                         {'id': '10024088', 'name': 'alina', 'age': 19},
65                         {'id': '10024089', 'name': 'allen', 'age': 20}
66                     ],
67                     'person': p1,
68                     'p_list': p_list,
69                     'size': 102400000,
70                     'now': now,
71                     'link': link,
72                     'script': script,
73                     'p_text': p_text,
74                     'msg': '上傳文件成功!',
75                     'img_dir': r"..\static\file\{}".format(file.name)
76                 })
傳遞的數據

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>模板標記語言學習---重點</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
</head>
<body>

{#增長導航條組件#}
{% include 'nav.html' %}

<div class="container" style="margin-top: 100px">
    <div class="row">
        <h3>Django模板語言以下:</h3>
        取字符串:
        <p>{{ data_str }}</p>
        <hr>
        取元組數據:
        <p>{{ data_tuple.0 }}</p>
        <p>{{ data_tuple.1 }}</p>
        <hr>
        取列表數據:
        <p>{{ data_list }}</p>
        <p>{{ data_list.0 }}</p>
        <p>{{ data_list.1 }}</p>
        <p>{{ data_list.2.id }}</p>
        <p>{{ data_list.2.name }}</p>
        <hr>
        取整個字典數據:
        <p>{{ data_dict }}</p>
        取字典中key對應的值
        <p>{{ data_dict.id }}</p>
        <p>{{ data_dict.name }}</p>
        <p>{{ data_dict.age }}</p>
        <p>{{ data_dict.items }}</p>
        <hr>
        循環列表:
        {% for lst in data_list %}
            <ul type="circle">
                <li style="color: #19ff24"><h5>{{ lst }}</h5></li>
            </ul>
        {% endfor %}
        <hr>
        嵌套(列表裏包含字典):
        {% for lst in data_list.2.values %}
            <ul type="circle">
                <li style="color: #ff3296"><h5>{{ lst }}</h5></li>
            </ul>
        {% endfor %}
        <hr>
        for循環 字典的key
        {% for item in data_dict %}
            <ul type="circle">
                <li style="color: blue"><h5>{{ item }}</h5></li>
            </ul>
        {% endfor %}

        for循環 字典的value
        {% for item in data_dict.values %}
            <ul type="square">
                <li style="color: red"><h5>{{ item }}</h5></li>
            </ul>
        {% endfor %}
        <hr>
        <div class="col-md-4">
            <table class="table table-bordered ">
                <thead>
                <tr>
                    <th>工號</th>
                    <th>姓名</th>
                    <th>年齡</th>
                    <th>操做</th>
                </tr>
                </thead>
                <tbody>
                {% for item in data %}
                    <tr>
                        <td>{{ item.id }}</td>
                        <td>{{ item.name }}</td>
                        <td>{{ item.age }}</td>
                        <td>
                            <a class="btn" href="/edit/?id={{ item.id }}">編輯</a>
                            <a class="btn" href="/del/?id={{ item.id }}">刪除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>

        {% if data_dict.id == '10024087' %}
            <p>工號爲:10024087的人員以下:</p>
            <p>姓名:{{ data_dict.name }}</p>
            <p>年齡:{{ data_dict.age }}</p>

        {% elif data_dict.id == '10024088' %}
            <p>工號爲:10024088的人員以下:</p>
            <p>姓名:{{ data_dict.name }}</p>
            <p>年齡:{{ data_dict.age }}</p>
        {% endif %}
    </div>
    <hr>
    <div>
        <h4>類對象:</h4>
        {{ person }}
        {{ person.name }} | {{ person.age }} | {{ person.sing }}
    </div>
    <hr>
    {{ p_list.0.name }} | {{ p_list.0.age }} | {{ p_list.0.sing }},
    {{ p_list.1.name }} | {{ p_list.1.age }} | {{ p_list.1.sing }}。
    <hr>
    <p>默認值 default</p>
    {{ bucunzai | default:'這個值不存在,使用默認值!' }}
    <hr>
    <p>長度 length 只輸出長度值</p>
    {{ data|length }}
    <hr>
    <p>文件大小:使用filesizeformat</p>
    {{ size|filesizeformat }}
    <hr>
    <h3>切片</h3>
    {{ data_list|slice:'1:-1' }}
    <hr>
    <h2>時間格式化</h2>
    <h4>{{ now|date:'Y-m-d H:i:s' }}</h4>
    <hr>
    <h2>safe</h2>
    {{ link|safe }}

    {#    {{ script|safe }}#}
    <hr>
    <h2>截取:truncatechars</h2>
    {{ p_text|truncatechars:50 }}
    <hr>
    <h2>自定義filter</h2>
    {% load my_filter %}
    {{ p_list.1.name }}
    {{ p_list.1.name|sb }}
    {{ p_list.1.name|str:'你是個SB' }}

    <hr>
    <div>
        <form action="/test/" method="post" enctype="multipart/form-data">
            <label for="">選擇文件:</label>
            <input name="file" type="file">
            <button type="submit">上傳</button>
        </form>
        <p style="color: blue">{{ msg }}</p>
    </div>
    <hr>
    {% if a > b > c %}
        <p>a>b>c</p>

    {% else %}
        <p>不成立</p>
    {% endif %}
    <hr>
    {% if a > b and b > c %}
        <p>a>b and b>c</p>
    {% else %}
        <p>不成立</p>
    {% endif %}
    <hr>
    <p>Django模板語言中,屬性的優先級大於方法的優先級</p>
    {{ data_dict.items }}
    <hr>
    <hr>
    {% for i in content3 %}
        <hr>
        外層循環:
        {{ forloop.counter }}
        {{ i }}
        {% for j in i %}
            <hr>
            內層循環:
            {{ forloop.counter }}
            <hr>
            {{ j }} @父循環:
            {{ forloop.parentloop.counter }}
        {% endfor %}

    {% endfor %}

    <div>
        <img src="{{ img_dir }}" alt="" height="600px" width="100%">
    </div>

    <hr>

    {#取普通變量#}
    {{ name }}
    {{ age }}

    取字典裏的key值
    {{ data_dict.keys.0 }}
</div>


<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
模板語言

 

 3.Filters(過濾)

(1)經常使用內置過濾

add 將參數增長到改值
{{ value|add:"2" }}
  
capfirst 將英文字符串第一個字母大寫
{{ value|capfirst }}

center  將內容居中
{{ value|center:"15" }}

cut 移除指定的字符
{{ value|cut:" " }}

date 格式化輸出時間
{{ value|date:"Y-m-d H:M:S" }}
{{ value|date:"Y年m月d日" }}

格式化字符    描述    示例輸出
a    'a.m.'或'p.m.'(請注意,這與PHP的輸出略有不一樣,由於這包括符合Associated Press風格的期間)    'a.m.'
A    'AM'或'PM'。    'AM'
b    月,文字,3個字母,小寫。    'jan'
B    未實現。
c    ISO 8601格式。 (注意:與其餘格式化程序不一樣,例如「Z」,「O」或「r」,若是值爲naive datetime,則「c」格式化程序不會添加時區偏移量(請參閱datetime.tzinfo) 。    2008-01-02T10:30:00.000123+02:00或2008-01-02T10:30:00.000123若是datetime是天真的
d    月的日子,帶前導零的2位數字。    '01'到'31'
D    一週中的文字,3個字母。    「星期五」
e    時區名稱 多是任何格式,或者可能返回一個空字符串,具體取決於datetime。    ''、'GMT'、'-500'、'US/Eastern'等
E    月份,特定地區的替表明示一般用於長日期表示。    'listopada'(對於波蘭語區域,而不是'Listopad')
f    時間,在12小時的小時和分鐘內,若是它們爲零,則分鐘停留。 專有擴展。    '1','1:30'
F    月,文,長。    '一月'
g    小時,12小時格式,無前導零。    '1'到'12'
G    小時,24小時格式,無前導零。    '0'到'23'
h    小時,12小時格式。    '01'到'12'
H    小時,24小時格式。    '00'到'23'
i    分鐘。    '00'到'59'
I    夏令時間,不管是否生效。    '1'或'0'
j    沒有前導零的月份的日子。    '1'到'31'
l    星期幾,文字長。    '星期五'
L    布爾值是不是一個閏年。    True或False
m    月,2位數字帶前導零。    '01'到'12'
M    月,文字,3個字母。    「揚」
n    月無前導零。    '1'到'12'
N    美聯社風格的月份縮寫。 專有擴展。    'Jan.','Feb.','March','May'
o    ISO-8601周編號,對應於使用閏年的ISO-8601週數(W)。 對於更常見的年份格式,請參見Y。    '1999年'
O    與格林威治時間的差別在幾小時內。    '+0200'
P    時間爲12小時,分鐘和'a.m。'/'p.m。',若是爲零,分鐘停留,特殊狀況下的字符串「午夜」和「中午」。 專有擴展。    '1 am','1:30 pm' / t3>,'midnight','noon','12:30 pm' / T10>
r    RFC 5322格式化日期。    'Thu, 21 Dec 2000 16:01:07 +0200'
s    秒,帶前導零的2位數字。    '00'到'59'
S    一個月的英文序數後綴,2個字符。    'st','nd','rd'或'th'
t    給定月份的天數。    28 to 31
T    本機的時區。    'EST','MDT'
u    微秒。    000000 to 999999
U    自Unix Epoch以來的二分之一(1970年1月1日00:00:00 UTC)。
w    星期幾,數字無前導零。    '0'(星期日)至'6'(星期六)
W    ISO-8601週數,週數從星期一開始。    1,53
y    年份,2位數字。    '99'
Y    年,4位數。    '1999年'
z    一年中的日子    0到365
Z    時區偏移量,單位爲秒。 UTC以西時區的偏移量老是爲負數,對於UTC以東時,它們老是爲正。    -43200到43200

default 若是一個變量是false或者爲空,使用給定的默認值。 不然,使用變量的值。
{{ value|default:"nothing"}}  若是value沒有傳值或者值爲空的話就顯示nothing

default_if_none 只有值爲None時才輸出指定的默認值
{{ value|default_if_none:"nothing" }}

dictsort 獲取字典列表並返回按參數中給出的鍵排序的列表
{{ value|dictsort:"name" }}
若是value是:

[
    {'name': 'zed', 'age': 19},
    {'name': 'amy', 'age': 22},
    {'name': 'joe', 'age': 31},
]
而後輸出將是:

[
    {'name': 'amy', 'age': 22},
    {'name': 'joe', 'age': 31},
    {'name': 'zed', 'age': 19},
]

divisibleby 若是值能被參數整除,則返回True
{{ value|divisibleby:"3" }}

filesizeformat 格式化輸出文件大小
{{ value|filesizeformat }}  若是value是123456789,則輸出爲117.7 MB

first 輸出列表中的第一個值
{{ value|first }}

floatformat 浮點數格式化輸出,
不指定參數狀況下,則將浮點數四捨五入後保留1位小數
value    Template    Output
34.23234    {{ value|floatformat }}    34.2
34.00000    {{ value|floatformat }}    34
34.26000    {{ value|floatformat }}    34.3

指定小數部分:
value    Template    Output
34.23234    {{ value|floatformat:3 }}    34.232
34.00000    {{ value|floatformat:3 }}    34.000
34.26000    {{ value|floatformat:3 }}    34.260

參數爲"0"時:它將浮點數四捨五入到最近的整數(個位數)。
value    Template    Output
34.23234    {{ value|floatformat:"0" }}    34
34.00000    {{ value|floatformat:"0" }}    34
39.56000    {{ value|floatformat:"0" }}    40

參數爲負數時,四捨五入後保留指定的小數位,可是隻顯示數字部分
value    Template    Output
34.23234    {{ value|floatformat:"-3" }}    34.232
34.00000    {{ value|floatformat:"-3" }}    34
34.26000    {{ value|floatformat:"-3" }}    34.260

join 使用字符串鏈接列表,例如Python的str.join(list)
{{ value|join:" // " }}
若是value是列表,則輸出將是字符串 。['a', 'b', 'c']"a // b // c"

last 返回列表中的最後一項
{{ value|last }}


length  返回值的長度
{{ value|length }}

length_is 若是值的長度是後面的參數,結果輸出True,不然輸出False

{{ value|length_is:"4" }}

ljust¶
左對齊給定寬度的字段中的值。
{{ value|ljust:"10" }}
若是value是Django,輸出將是。"Django    "
  
lower 將字符串轉換爲所有小寫。
{{ value|lower }}

random 返回給定列表中的隨機項。
{{ value|random }}若是value是列表,則輸出能夠是。['a', 'b', 'c', 'd']"b"

safe
Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。
可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,
這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤
的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的
方式告訴Django這段代碼是安全的沒必要轉義。

value = "<a href='#'>點我</a>"
{{ value|safe}}

slice 切片
{{value|slice:"2:-1"}}
{{ some_list|slice:":2" }}  若是some_list是,輸出將是。['a', 'b', 'c']['a', 'b']

striptags 盡一切努力去除全部[X] HTML標記。
{{ value|striptags }}
若是value是,輸出將是。"<b>Joel</b> <button>is</button> a <span>slug</span>""Joel is a slug"

time 根據給定的格式格式化時間。
{{ value|time:"H:i" }}

timesince
將日期格式設爲自該日期起的時間(例如,「4天,6小時」)。

採用一個可選參數,它是一個包含用做比較點的日期的變量(不帶參數,比較點爲如今)。
例如,若是blog_date是表示2006年6月1日午夜的日期實例,而且comment_date是2006年6月1日08:00的日期實例,
則如下將返回「8小時」:
{{ blog_date|timesince:comment_date }}
分鐘是所使用的最小單位,對於相對於比較點的將來的任何日期,將返回「0分鐘」。

timeuntil
似於timesince,除了它測量從如今開始直到給定日期或日期時間的時間。 例如,若是今天是2006年6月1日,
而conference_date是保留2006年6月29日的日期實例,則{{ conference_date | timeuntil }}將返回「4周」。
使用可選參數,它是一個包含用做比較點的日期(而不是如今)的變量。 若是from_date包含2006年6月22日,
則如下內容將返回「1周」:
{{ conference_date|timeuntil:from_date }}

title 英文字符串的每一個單詞首字母大寫
{{ value|title }}

truncatechars 若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
{{ value|truncatechars:9}}

truncatewords 在必定數量的字後截斷字符串
{{ value|truncatewords:2 }}

upper 將字符串轉換爲所有大寫。
{{ value|upper }}

urlize 將文本中的URL和電子郵件地址轉換爲可單擊的連接。
{{ value|urlize }}

urlizetrunc 將URL和電子郵件地址轉換爲可點擊的連接,就像urlize同樣,但會截斷超過給定字符限制的URL。
{{ value|urlizetrunc:15 }}

wordcount 返回單詞數量
{{ value|wordcount }}
經常使用內置過濾器

 

(2)自定義過濾

自定義過濾器只是帶有一個或兩個參數的Python函數:

  • 變量(輸入)的值 - -不必定是一個字符串
  • 參數的值 - 這能夠有一個默認值,或徹底省略

例如,在過濾器{{var | foo:'bar'}}中,過濾器foo將傳遞變量var和參數「bar」

自定義filter代碼文件擺放位置:

app01/
    __init__.py
    models.py
    templatetags/  # 在app01下面新建一個package package
        __init__.py
        app01_filters.py  # 建一個存放自定義filter的文件
    views.py

  

編寫自定義filter

from django import template
register = template.Library()
 
 
@register.filter(name="cut")
def cut(value, arg):
    return value.replace(arg, "")
 
 
@register.filter(name="addSB")
def add_sb(value):
    return "{} SB".format(value)

  

使用自定義filter

{# 先導入咱們自定義filter那個文件 #}
{% load app01_filters %}
 
{# 使用咱們自定義的filter #}
{{ somevariable|cut:"0" }}
{{ d.name|addSB }}

  

1.定義
在app下面新建python包:templatetags
2.在新建的包中,新建一個python文件
3.在上訴python文件中:
    from django import template

    生成一個註冊的實例
    register = template.Library()

    定義並註冊一個自定義filter函數

    @register.filter(name="add_str")
    def add_str(arg):
        return "{} hello".format(arg)

4.調用階段:(
    1.在django模板文件中(HTML文件中),導入剛纔新建的Python文件
    {% load py文件名 %}

    2.按照filter的語法調用
        {{ name | add_str }}
自定義過濾器

 

4.邏輯相關

(1)for循環

普通for循環

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
    <li>{{ user.age}}</li>
{% endfor %}
</ul>

 

for循環能夠用的參數:

Variable Description
forloop.counter 當前循環的索引值(從1開始)
forloop.counter0 當前循環的索引值(從0開始)
forloop.revcounter 當前循環的倒序索引值(從1開始)
forloop.revcounter0 當前循環的倒序索引值(從0開始)
forloop.first 當前循環是否是第一次循環(布爾值)
forloop.last 當前循環是否是最後一次循環(布爾值)
forloop.parentloop 本層循環的外層循環

 

 

 

 

 

 

 

 for...empty

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>

 

(2)if條件判斷

{% if condition1 %}
    ...
{% elif condition2 %}
    ...
{% else %}
    ...
{% endif %}

  

<td>
    {% if each.st == 0 %}
        {#                                            <p>暫停</p>#}
        <i class="fa fa-pause fa-2x" style="color: #ffea51"></i>
    {% elif each.st == 1 %}
        {#                                            <p>運行</p>#}
        <i class="fa fa-cog fa-spin fa-2x" style="color: green"></i>
    {% elif each.st == -1 %}
        {#                                            <p>離線</p>#}
        <i class="fa fa-power-off fa-2x" style="color: black"></i>
    {% endif %}
</td>

if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷。

{% if athlete_list and coach_list %}
    Both athletes and coaches are available.
{% endif %}

{% if not athlete_list %}
    There are no athletes.
{% endif %}

{% if athlete_list or coach_list %}
    There are some athletes or some coaches.
{% endif %}

{% if not athlete_list or coach_list %}
    There are no athletes or there are some coaches.
{% endif %}

{% if athlete_list and not coach_list %}
    There are some athletes and absolutely no coaches.
{% endif %}

{% if athlete_list and coach_list or cheerleader_list %}
{% endif %}

{% if somevar == "x" %}
  This appears if variable somevar equals the string "x"
{% endif %}

{% if somevar != "x" %}
  This appears if variable somevar does not equal the string "x",
  or if somevar is not found in the context
{% endif %}

{% if somevar < 100 %}
  This appears if variable somevar is less than 100.
{% endif %}

{% if somevar > 0 %}
  This appears if variable somevar is greater than 0.
{% endif %}

{% if somevar <= 100 %}
  This appears if variable somevar is less than 100 or equal to 100.
{% endif %}

{% if somevar >= 1 %}
  This appears if variable somevar is greater than 1 or equal to 1.
{% endif %}

{% if "bc" in "abcdef" %}
  This appears since "bc" is a substring of "abcdef"
{% endif %}

{% if "hello" in greetings %}
  If greetings is a list or set, one element of which is the string
  "hello", this will appear.
{% endif %}

{% if user in users %}
  If users is a QuerySet, this will appear if user is an
  instance that belongs to the QuerySet.
{% endif %}

{% if somevar is True %}
  This appears if and only if somevar is True.
{% endif %}

{% if somevar is None %}
  This appears if somevar is None, or if somevar is not found in the context.
{% endif %}

{% if somevar is not True %}
  This appears if somevar is not True, or if somevar is not found in the
  context.
{% endif %}

{% if somevar is not None %}
  This appears if and only if somevar is not None.
{% endif %}

  

(3)with

  定義一箇中間變量,多用於給一個複雜的變量起別名。

注意等號左右不要加空格。

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

{% with business.employees.count as total %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

 

5.母版和繼承母版

   咱們在編寫多個HTML內容時,爲了不編寫重複的內容和更方便修改部份內容時,一般提取相同的內容做爲母版。

以下內容:文件名定義爲 base.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  {% block page-css %}
  
  {% endblock %}
</head>
<body>

<h1>這是母板的標題</h1>

{% block page-main %}

{% endblock %}
<h1>母板底部內容</h1>
{% block page-js %}

{% endblock %}
</body>
</html>

  
注意:咱們一般會在母板中定義頁面專用的CSS塊和JS塊,方便子頁面替換。

 

繼承母版:在子頁面中在頁面最上方使用下面的語法來繼承母板。

{% extends 'layouts.html' %}

  

具體使用的步驟
1.把共用的HTML部分提取出來,放到base.html文件中
2.在base.html中,經過定義block,把每一個頁面不一樣的部分分出來
3.在具體的頁面中,先繼承母版
4.而後block 名 去指定替換母版相應的位置

注意事項:
1.{% extends 'base.html' %}     母版文件,base.html要加引號
2.{% extends 'base.html' %}     必須放在子頁面的第一行
3.能夠在base.html中定義不少block ,一般和咱們會額外定義page_css和page_js兩個塊
4.view.py 相應的函數中返回的是對應的子頁面文件,不是 base.html

  

6.塊(block)

 經過在母板中使用{% block  xxx %}來定義"塊"。

 在子頁面中經過定義母板中的block名來對應替換母板中相應的內容。

{% block page-main %}
  <p>繼承母版後,新的內容部分</p> 
{% endblock %}

  

7.組件

能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可。

{% include 'navbar.html' %}

 

 8.靜態文件相關

加載settings.py文件中的static別名
{% load static %}
{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
自動在別名下去查找對應的文件
<link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'Dashboard_files/dashboard.css' %}" rel="stylesheet">
<script src="{% static 'jquery-3.3.1.min.js' %}"></script>
<script src="{% static 'bootstrap/js/bootstrap.js' %}"></script>

某個文件多處被用到能夠存爲一個變量
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

獲取靜態文件路徑
{% get_static_prefix %}
使用:
    {% load static %}
    <link href="{% get_static_prefix %}Dashboard_files/dashboard.css" rel="stylesheet">

{% get_static_prefix %}
{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者
{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

  

9.simple_tag

和自定義filter相似,只不過接收更靈活的參數。

定義註冊simple tag

@register.simple_tag(name="plus")
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)

使用自定義simple tag

{% load app01_demo %}

{# simple tag #}
{% plus "1" "2" "abc" %}

 

10.inclusion_tag

多用於返回html代碼片斷

示例:

templatetags/my_inclusion.py

from django import template
 
register = template.Library()
 
@register.inclusion_tag('result.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}項".format(i) for i in range(1, n+1)]
    return {"data": data}

  

templates/snippets/result.html

<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>

  

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>inclusion_tag test</title>
</head>
<body>

{% load inclusion_tag_test %}

{% show_results 10 %}
</body>
</html>

  

3、Django視圖(View)系統

 1.概念

一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求而且返回Web響應。

響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。

不管視圖自己包含什麼邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你當前項目目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。爲了將代碼放在某處,你們約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名爲views.py的文件中。

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

  

讓咱們來逐行解釋下上面的代碼:

  • 首先,咱們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫。

  • 接着,咱們定義了current_datetime函數。它就是視圖函數。每一個視圖函數都使用HttpRequest對象做爲第一個參數,而且一般稱之爲request

    注意,視圖函數的名稱並不重要;不須要用一個統一的命名方式來命名,以便讓Django識別它。咱們將其命名爲current_datetime,是由於這個名稱可以比較準確地反映出它實現的功能。

  • 這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都負責返回一個HttpResponse對象。

Django使用請求和響應對象來經過系統傳遞狀態。

當瀏覽器向服務端請求一個頁面時,Django建立一個HttpRequest對象,該對象包含關於請求的元數據。而後,Django加載相應的視圖,將這個HttpRequest對象做爲第一個參數傳遞給視圖函數。

每一個視圖負責返回一個HttpResponse對象。

 

2.FBV和CBV

基於函數的view,就叫FBV

def pub_list(request):
    ipaddr = request.META['REMOTE_ADDR']
    all_data = main()
    return render(request, 'pub_list.html', {'all_data': all_data, 'ipaddr': ipaddr})

  

基於類的view,就叫CBV,且先導入from django.views import View類,再繼承

class Upload(View):
    def get(self, request):
        return render(request, 'test2.html')

    def post(self, request):
        file_name = request.FILES.get('upload_file')
        print(file_name.size)
        with open(os.path.join(BASE_DIR, 'static', 'file', file_name.name), 'wb') as f:
            for chunk in file_name.chunks():
                f.write(chunk)
        return HttpResponse('上傳成功!')

  

基於類的視圖,還須要在urls.py文件中,修改對應關係;view.類名.as_view()

url(r'^test2/', views.Upload.as_view()),

  

3.Request對象和Response對象

官網

(1)Request對象

當一個頁面被請求時,Django就會建立一個包含本次請求原信息的HttpRequest對象。Django會將這個對象自動傳遞給響應的視圖函數,通常視圖函數約定俗成地使用 request 參數承接這個對象。

1.HttpRequest.body 請求體,byte類型 request.POST的數據就是從body裏面提取到的

2.HttpRequest.path 表示所請求頁面的完整路徑的字符串,不包括域名 例: "/music/bands/the_beatles/"

3.HttpRequest.path_info 返回用戶訪問url,不包括域名

4.HttpRequest.method  請求中使用的HTTP方法的字符串表示,全大寫表示
    if request.method == 'GET':
        do_something()
    elif request.method == 'POST':
        do_something_else()

5.HttpRequest.encoding   一個字符串,表示提交的數據的編碼方式(若是爲 None 則表示使用 DEFAULT_CHARSET 的設置,默認爲 'utf-8')。
   這個屬性是可寫的,你能夠修改它來修改訪問表單數據使用的編碼。
   接下來對屬性的任何訪問(例如從 GET 或 POST 中讀取數據)將使用新的 encoding 值。
   若是你知道表單數據的編碼不是 DEFAULT_CHARSET ,則使用它。

6.HttpRequest.content_type  表示請求的MIME類型的字符串,從CONTENT_TYPE標頭解析 。


7.HttpRequest.content_params    CONTENT_TYPE 標題中包含的鍵/值參數字典。

8.HttpRequest.GET   一個相似於字典的對象,包含 HTTP GET 的全部參數。詳情請參考 QueryDict 對象。

9.HttpRequest.POST  一個相似於字典的對象,若是請求中包含表單數據,則將這些數據封裝成 QueryDict 對象。
    POST 請求能夠帶有空的 POST 字典 —— 若是經過 HTTP POST 方法發送一個表單,可是表單中沒有任何的數據,QueryDict 對象依然會被建立。
    所以,不該該使用 if request.POST  來檢查使用的是不是POST 方法;應該使用 if request.method == "POST"

  另外:若是使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中。

10.HttpRequest.COOKIES  包含全部cookie的字典。鍵和值是字符串。

11.HttpRequest.FILES      一個相似於字典的對象,包含全部的上傳文件信息。FILES 中的每一個鍵爲<input type="file" name="" /> 中的name,值則爲對應的數據。
  注意,FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會包含數據。不然,FILES 將爲一個空的相似於字典的對象。

12.HttpRequest.META 一個標準的Python 字典,包含全部的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例:
    CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。
    CONTENT_TYPE —— 請求的正文的MIME 類型。
    HTTP_ACCEPT —— 響應可接收的Content-Type。
    HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。
    HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。
    HTTP_HOST —— 客服端發送的HTTP Host 頭部。
    HTTP_REFERER —— Referring 頁面。
    HTTP_USER_AGENT —— 客戶端的user-agent 字符串。
    QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。
    REMOTE_ADDR —— 客戶端的IP 地址。
    REMOTE_HOST —— 客戶端的主機名。
    REMOTE_USER —— 服務器認證後的用戶。
    REQUEST_METHOD —— 一個字符串,例如"GET""POST"。
    SERVER_NAME —— 服務器的主機名。
    SERVER_PORT —— 服務器的端口(是一個字符串)。
   從上面能夠看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,請求中的任何 HTTP 首部轉換爲 META 的鍵時,
    都會將全部字母大寫並將鏈接符替換爲下劃線最後加上 HTTP_  前綴。
    因此,一個叫作 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。

13.HttpRequest.resolver_match
ResolverMatch表示已解析URL 的實例。此屬性僅在URL解析發生後設置,這意味着它在全部視圖中均可用,但在URL解析發生以前執行的中間件中不可用(process_view()儘管可使用它 )。
HttpRequest對象屬性

 

1.HttpRequest.current_app  The url template tag will use its value as the current_app argument to reverse().

2.HttpRequest.urlconf   This will be used as the root URLconf for the current request, overriding the ROOT_URLCONF setting. See How Django processes a request for details.
urlconf can be set to None to revert any changes made by previous middleware and return to using the ROOT_URLCONF.
經過應用程序設置的屬性

 

1.HttpRequest.session 來自SessionMiddleware:一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。完整的細節參見會話的文檔。

2.HttpRequest.site  來自CurrentSiteMiddleware: 表示當前站點返回的實例Site或 RequestSite返回 的實例get_current_site()。

3.HttpRequest.user  來自AuthenticationMiddleware:AUTH_USER_MODEL表示當前登陸用戶的實例。若是用戶當前未登陸,user則將其設置爲實例AnonymousUser。您能夠將它們區分開來 is_authenticated,以下所示:

    if request.user.is_authenticated:
        ... # Do something for logged-in users.
    else:
        ... # Do something for anonymous users.

****************************************************************************************************************************************************************
    匿名用戶
    class models.AnonymousUser

    django.contrib.auth.models.AnonymousUser 類實現了django.contrib.auth.models.User 接口,但具備下面幾個不一樣點:

    id 永遠爲None。
    username 永遠爲空字符串。
    get_username() 永遠返回空字符串。
    is_staff 和 is_superuser 永遠爲False。
    is_active 永遠爲 False。
    groups 和 user_permissions 永遠爲空。
    is_anonymous() 返回True 而不是False。
    is_authenticated() 返回False 而不是True。
    set_password()、check_password()、save() 和delete() 引起 NotImplementedError。
    New in Django 1.8:
    新增 AnonymousUser.get_username() 以更好地模擬 django.contrib.auth.models.User。
經過中間件設置的屬性

 

1.HttpRequest.get_host()

  根據從HTTP_X_FORWARDED_HOST(若是打開 USE_X_FORWARDED_HOST,默認爲False)和 HTTP_HOST 頭部信息返回請求的原始主機。
   若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。

  USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的狀況下,才能夠被使用。

  例如:"127.0.0.1:8000"

  注意:當主機位於多個代理後面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。

 

2.HttpRequest.get_full_path()

  返回 path,若是能夠將加上查詢字符串。

  例如:"/music/bands/the_beatles/?print=true"

 

3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

  返回簽名過的Cookie 對應的值,若是簽名再也不合法則返回django.core.signing.BadSignature。

  若是提供 default 參數,將不會引起異常並返回 default 的值。

  可選參數salt 能夠用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。

        複製代碼
        >>> request.get_signed_cookie('name')
        'Tony'
        >>> request.get_signed_cookie('name', salt='name-salt')
        'Tony' # 假設在設置cookie的時候使用的是相同的salt
        >>> request.get_signed_cookie('non-existing-cookie')
        ...
        KeyError: 'non-existing-cookie'    # 沒有相應的鍵時觸發異常
        >>> request.get_signed_cookie('non-existing-cookie', False)
        False
        >>> request.get_signed_cookie('cookie-that-was-tampered-with')
        ...
        BadSignature: ...    
        >>> request.get_signed_cookie('name', max_age=60)
        ...
        SignatureExpired: Signature age 1677.3839159 > 60 seconds
        >>> request.get_signed_cookie('name', False, max_age=60)
        False
        複製代碼
         


4.HttpRequest.is_secure()

  若是請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。

 

5.HttpRequest.is_ajax()

  若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'。

  大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。

  若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware, 
   你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。
方法

 

注意:鍵值對的值是多個的時候,好比checkbox類型的input標籤,select標籤,須要用:

request.POST.getlist("hobby")

 

#FBV
def upload(request):
    """
    保存上傳文件前,數據須要存放在某個位置。默認當上傳文件小於2.5M時,django會將上傳文件的所有內容讀進內存。從內存讀取一次,寫磁盤一次。
    但當上傳文件很大時,django會把上傳文件寫到臨時文件中,而後存放到系統臨時文件夾中。
    :param request: 
    :return: 
    """
    if request.method == "POST":
        # 從請求的FILES中獲取上傳文件的文件名,file爲頁面上type=files類型input的name屬性值
        filename = request.FILES["file"].name
        # 在項目目錄下新建一個文件
        with open(filename, "wb") as f:
            # 從上傳的文件對象中一點一點讀
            for chunk in request.FILES["file"].chunks():
                # 寫入本地文件
                f.write(chunk)
        return HttpResponse("上傳OK")

#CBV 
class Upload(View):
    def get(self, request):
        return render(request, 'test2.html')

    def post(self, request):
        print(request.FILES)
        # print(request.FILES['upload_file'])
        # print(request.FILES['upload_file'].name)
        print(request.FILES.get('upload_file'))
        file_name = request.FILES.get('upload_file')
        print(file_name.size)

        with open(os.path.join(BASE_DIR, 'static', 'file', file_name.name), 'wb') as f:
            for chunk in file_name.chunks():
                f.write(chunk)
        return HttpResponse('上傳成功!')
上傳文件示例
<form class="form-inline" action="/test2/" method="post" enctype="multipart/form-data">
    <input type="file" name="upload_file">
    <button class="btn btn-primary" type="submit">上傳文件</button>
</form>
上傳文件之HTML form表單

 

 (2)Response對象

  與由Django自動建立的HttpRequest對象相比,HttpResponse對象是咱們的職責範圍了。咱們寫的每一個視圖都須要實例化,填充和返回一個HttpResponse。

HttpResponse類位於django.http模塊中。

做用:

典型用法是將頁面內容做爲字符串傳遞給 HttpResponse構造函數:
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")

可是,若是要以增量方式添加內容,能夠將其response用做類文件對象:
>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

設置或刪除響應頭信息
>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']

請注意,與字典不一樣,若是標題字段不存在,del則不會引起KeyError。

要告訴瀏覽器將響應視爲文件附件,請使用 content_type參數並設置Content-Disposition標頭。例如,這是您返回Microsoft Excel電子表格的方式:
>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'

  

1.HttpResponse.content  表示內容的字節字符串,必要時從Unicode對象編碼。

2.HttpResponse.charset  一個字符串,表示將在其中編碼響應的字符集。若是未在HttpResponse實例化時間給出,則將從中提取 content_type,若是不成功,DEFAULT_CHARSET則將使用該 設置。

3.HttpResponse.status_code  響應的 HTTP狀態代碼。除非reason_phrase明確設置,不然修改 status_code構造函數外部的值也會修改值 reason_phrase。

4.HttpResponse.reason_phrase    響應的HTTP緣由短語。它使用了HTTP標準的默認緣由短語。除非明確設置,不然reason_phrase由值肯定 status_code。

5.HttpResponse.streaming    這老是返回False。此屬性存在,表示中間件不一樣於常規響應處理流式響應。

6.HttpResponse.closed   若是回覆關閉返回True。
屬性

 

4.JsonResponse對象

  JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。

from django.http import JsonResponse

response = JsonResponse({'foo': 'bar'})
print(response.content)

b'{"foo": "bar"}'
默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數。

response = JsonResponse([1, 2, 3], safe=False)

def json_test(request):
    data1 = {'name': 'felix', 'age': 18}
    data2 = [11, 22, 33, 44, 55]
    # import json
    # data_str = json.dumps(data1)
    # return HttpResponse(data_str)
    # JsonResponse只支持序列化字典,不支持列表,返回列表須要增長safe=False參數
    from django.http import JsonResponse
    return JsonResponse(data2, safe=False)

  

5.Django shortcut functions

(1)render()

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。

參數:
     request: 用於生成響應的請求對象。

     template_name:要使用的模板的完整名稱,可選的參數

     context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。

     content_type:生成的文檔要使用的MIME類型。默認爲 DEFAULT_CONTENT_TYPE 設置的值。默認爲'text/html'

     status:響應的狀態碼。默認爲200。

   useing: 用於加載模板的模板引擎的名稱。

from django.shortcuts import render

def my_view(request):
    # View code here...
    return render(request, 'myapp/index.html', {
        'foo': 'bar',
    }, content_type='application/xhtml+xml')
這個例子至關於:

from django.http import HttpResponse
from django.template import loader

def my_view(request):
    # View code here...
    t = loader.get_template('myapp/index.html')
    c = {'foo': 'bar'}
    return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')

  

 (2)redirect() 重定向

參數能夠是:

  • 一個模型:將調用模型的get_absolute_url() 函數
  • 一個視圖,能夠帶有參數:將使用urlresolvers.reverse 來反向解析名稱
  • 一個絕對的或相對的URL,將原封不動的做爲重定向的位置。

默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。

 

傳遞一個具體的ORM對象
將調用具體ORM對象的get_absolute_url() 方法來獲取重定向的URL:

from django.shortcuts import redirect
 
def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object)

傳遞一個視圖的名稱
def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

傳遞要重定向到的一個具體的網址
def my_view(request):
    ...
    return redirect('/some/url/')

固然也能夠是一個完整的網址
def my_view(request):
    ...
    return redirect('http://example.com/')

默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:

def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object, permanent=True)  

  

4、Django路由系統

1.URLconf配置
  URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表。

 

基本格式:

from django.conf.urls import url

urlpatterns = [
     url(正則表達式, views視圖函數,參數,別名),
]

  

參數格式:

  • 正則表達式:一個正則表達式字符串
  • views視圖函數:一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串
  • 參數:可選的要傳遞給視圖函數的默認參數(字典形式)
  • 別名:一個可選的name參數

 

from django.urls import path

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
Django 2.0版本格式

 

 

2.正則表達式詳解---分組匹配

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

  

注意事項:

  • urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則再也不繼續。
  • 若要從URL中捕獲一個值,只須要在它周圍放置一對圓括號(分組匹配)。
  • 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。
  • 每一個正則表達式前面的'r' 是可選的可是建議加上。

補充說明:

# 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項
APPEND_SLASH=True

 Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其做用就是自動在網址結尾加'/'。

 

分組匹配  --->   至關於給視圖函數傳遞位置參數

分組命名匹配 --->  至關於給視圖函數傳遞關鍵字參數

 

3.分組命名匹配

(1)分組命名匹配示例

上面的示例使用簡單的正則表達式分組匹配(經過圓括號)來捕獲URL中的值並以位置參數形式傳遞給視圖。

在更高級的用法中,可使用分組命名匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖。

在Python的正則表達式中,分組命名正則表達式組的語法是(?P<name>pattern),其中name是組的名稱,pattern是要匹配的模式。

 

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),

  

這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。

例如,針對url /articles/2017/12/至關於按如下方式調用視圖函數:

views.month_archive(request, year="2017", month="12")

 

(2)分組命名匹配的位置

  URLconf 在請求的URL 上查找,將它當作一個普通的Python 字符串。不包括GET和POST參數以及域名。

例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/。

在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/

URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POSTGETHEAD等等 —— 都將路由到相同的函數。

 

(3)捕獲的參數永遠都是字符串

每一個在URLconf中捕獲的參數都做爲一個普通的Python字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

傳遞到視圖函數views.year_archive() 中的year 參數永遠是一個字符串類型。

 

(4)視圖函數中指定默認值

# urls.py中
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py中,能夠爲num指定默認值
def page(request, num="1"):
    pass

在上面的例子中,兩個URL模式指向相同的view - views.page - 可是第一個模式並無從URL中捕獲任何東西。

若是第一個模式匹配上了,page()函數將使用其默認參數num=「1」,若是第二個模式匹配,page()將使用正則表達式捕獲到的num值。

 

(5)include其餘的URLconfs

a.主項目和子項目的urls分別在不一樣的urls.py文件中,主項目include子項目中的urls

from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),  # 能夠包含其餘的URLconfs文件
]

  

 

請注意,此示例中的正則表達式沒有$ (字符串結尾匹配字符),但包含尾部斜槓。每當Django遇到include()django.conf.urls.include())時,

它都會刪除與該點匹配的URL的任何部分,並將剩餘的字符串發送到包含的URLconf以進行進一步處理。

 

b.主項目和子項目URLS分組寫,主項目include子項目中的URLS

 另外一種可能性是經過使用url()實例列表來包含其餘URL模式 例如,考慮這個URLconf:

from django.conf.urls import include, url

from apps.main import views as main_views
from credit import views as credit_views

extra_patterns = [
    url(r'^reports/$', credit_views.report),
    url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
    url(r'^charge/$', credit_views.charge),
]

urlpatterns = [
    url(r'^$', main_views.homepage),
    url(r'^help/', include('apps.help.urls')),
    url(r'^credit/', include(extra_patterns)),
]

在此示例中,/credit/reports/URL將由credit_views.report()Django視圖處理 

 

c.刪除冗餘url

這可用於從重複使用單個模式前綴的URLconf中刪除冗餘。例如,考慮這個URLconf:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]

  

咱們能夠經過僅指定公共路徑前綴一次並對不一樣的後綴進行分組來改進這一點:

from django.conf.urls import include, url
from . import views

urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
        url(r'^history/$', views.history),
        url(r'^edit/$', views.edit),
        url(r'^discuss/$', views.discuss),
        url(r'^permissions/$', views.permissions),
    ])),
]

  

 

5、Django模型(model)系統

1.ORM介紹

  對象-關係映射(Object/Relation Mapping,簡稱ORM),是隨着面向對象的軟件開發方法發展而產生的。面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,
關係數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關係數據是業務實體的兩種表現形式,業務實體在內存中表現爲對象,在數據庫中表現爲關係數據。
內存中的對象之間存在關聯和繼承關係,而在數據庫中,關係數據沒法直接表達多對多關聯和繼承關係。所以,對象-關係映射(ORM)系統通常以中間件的形式存在,
主要實現程序對象到關係數據庫數據的映射。簡單的說:ORM至關於中繼數據,操做數據、

2.Django中的ORM

Django項目中使用MySQL數據庫

 (1)在Django項目的settings.py文件中,配置數據庫鏈接信息:

DATABASES = {
    'default': {
        # 鏈接的數據庫類型
        'ENGINE': 'django.db.backends.mysql',
        # 數據庫的地址
        'HOST': '127.0.0.1',
        # 數據庫使用的端口
        'PORT': '3306',
        # 所鏈接的數據庫名字
        'NAME': 'book',
        # 鏈接數據庫的用戶名
        'USER': 'root',
        # 鏈接數據庫的密碼
        'PASSWORD': ''
    }
}

  

(2)在Django項目的__init__.py文件中寫以下代碼,告訴Django使用pymysql模塊鏈接MySQL數據庫:

import pymysql

pymysql.install_as_MySQLdb()

  

 Model

在Django中model是你數據的單1、明確的信息來源。它包含了你存儲的數據的重要字段和行爲。一般,一個模型(model)映射到一個數據庫表,

基本狀況:

  • 每一個模型都是一個Python類,它是django.db.models.Model的子類。
  • 模型的每一個屬性都表明一個數據庫字段。
  • 綜上所述,Django爲您提供了一個自動生成的數據庫訪問API,詳詢官方文檔連接

 

 

下面這個例子定義了一個 Person 模型,包含 first_name 和 last_name。

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
first_name 和 last_name 是模型的字段。每一個字段被指定爲一個類屬性,每一個屬性映射到一個數據庫列。

上面的 Person 模型將會像這樣建立一個數據庫表:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);
一些說明:

表myapp_person的名稱是自動生成的,若是你要自定義表名,須要在model的Meta類中指定 db_table 參數,強烈建議使用小寫表名,特別是使用MySQL做爲後端數據庫時。
id字段是自動添加的,若是你想要指定自定義主鍵,只需在其中一個字段中指定 primary_key=True 便可。若是Django發現你已經明確地設置了Field.primary_key,它將不會添加自動ID列。
本示例中的CREATE TABLE SQL使用PostgreSQL語法進行格式化,但值得注意的是,Django會根據配置文件中指定的數據庫後端類型來生成相應的SQL語句。
Django支持MySQL5.5及更高版本。
示例

 

 

 3.經常使用字段(官網字段介紹)

AutoField
自增 int自增列,必須填入參數 primary_key=True。當model中若是沒有自增列,則自動會建立一個列名爲id的列。

IntegerField
一個整數類型,範圍在 -2147483648 to 2147483647

CharField
varchar 字符類型,必須提供max_length參數, max_length表示字符長度。

DateField
日期字段,日期格式  YYYY-MM-DD,至關於Python中的datetime.date()實例。

DateTimeField
日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime()實例。

    DatetimeField、DateField、TimeField這個三個時間字段,均可以設置以下屬性。
    
    auto_now_add
    配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。
    
    auto_now
    配置上auto_now=True,每次更新數據記錄的時候會更新該字段。

  

   AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 0 ~ 32767
    IntegerField(Field)
        - 整數列(有符號的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須爲逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          容許文件
                allow_folders=False,       容許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型
字段集合

 

 

4.自定義字段

class UnsignedIntegerField(models.IntegerField):
    def db_type(self, connection):
        return 'integer UNSIGNED'

自定義char類型字段:

複製代碼
class FixedCharField(models.Field):
    """
    自定義的char類型的字段類
    """
    def __init__(self, max_length, *args, **kwargs):
        super().__init__(max_length=max_length, *args, **kwargs)
        self.length = max_length

    def db_type(self, connection):
        """
        限定生成數據庫表的字段類型爲char,長度爲length指定的值
        """
        return 'char(%s)' % self.length


class Class(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=25)
    # 使用上面自定義的char類型的字段
    cname = FixedCharField(max_length=25)
複製代碼

建立的表結構:

 

對應關係:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
ORM字段與數據庫實際字段的對應關係

 

 

5.字段參數

null
用於表示某個字段能夠爲空。

unique
若是設置爲unique=True 則該字段在此表中必須是惟一的 。

db_index
若是db_index=True 則表明着爲此字段設置數據庫索引。

default
爲該字段設置默認值。

DatetimeField、DateField、TimeField這個三個時間字段,均可以設置以下屬性。

auto_now_add
配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。

auto_now
配置上auto_now=True,每次更新數據記錄的時候會更新該字段。

  

6.關係字段

(1)ForeignKey

  外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。ForeignKey能夠和其餘表作關聯關係同時也能夠和自身作關聯關係。

 

字段參數:

1.to
設置要關聯的表

2.to_field
設置要關聯的表的字段

3.related_name
反向操做時,使用的字段名,用於代替原反向查詢時的'表名_set'。

例如:
class Classes(models.Model):
    name = models.CharField(max_length=32)

class Student(models.Model):
    name = models.CharField(max_length=32)
    theclass = models.ForeignKey(to="Classes")
當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫:

models.Classes.objects.first().student_set.all()
當咱們在ForeignKey字段中添加了參數 related_name 後,

class Student(models.Model):
    name = models.CharField(max_length=32)
    theclass = models.ForeignKey(to="Classes", related_name="students")
當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫:

models.Classes.objects.first().students.all()

4.related_query_name
反向查詢操做時,使用的鏈接前綴,用於替換表名。

5.on_delete
當刪除關聯表中的數據時,當前表與其關聯的行的行爲。

models.CASCADE
刪除關聯數據,與之關聯也刪除


models.DO_NOTHING
刪除關聯數據,引起錯誤IntegrityError


models.PROTECT
刪除關聯數據,引起錯誤ProtectedError


models.SET_NULL
刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空)


models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值)


models.SET

刪除關聯數據,
a. 與之關聯的值設置爲指定值,設置:models.SET(值)
b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)

def func():
    return 10

class MyModel(models.Model):
    user = models.ForeignKey(
        to="User",
        to_field="id",
        on_delete=models.SET(func)
    )

6.db_constraint
是否在數據庫中建立外鍵約束,默認爲True。

  

(2)OneToOneField

   一對一字段。一般一對一字段用來擴展已有字段。一對一的關聯關係多用在當一張表的不一樣字段查詢頻次差距過大的狀況下,將本能夠存儲在一張表的字段拆開放置在兩張表中,而後將兩張表創建一對一的關聯關係。

class Author(models.Model):
    name = models.CharField(max_length=32)
    info = models.OneToOneField(to='AuthorInfo')
    

class AuthorInfo(models.Model):
    phone = models.CharField(max_length=11)
    email = models.EmailField()

  

字段參數:

to
設置要關聯的表。

to_field
設置要關聯的字段。

on_delete
同ForeignKey字段。

  

(3)ManyToManyField

  用於表示多對多的關聯關係。在數據庫中經過第三張表來創建關聯關係。

字段參數:
1.to
設置要關聯的表

2.related_name
同ForeignKey字段。

3.related_query_name
同ForeignKey字段。

4.symmetrical
僅用於多對多自關聯時,指定內部是否建立反向操做的字段。默認爲True。
    
class Person(models.Model):
    name = models.CharField(max_length=16)
    friends = models.ManyToManyField("self")
此時,person對象就沒有person_set屬性。

class Person(models.Model):
    name = models.CharField(max_length=16)
    friends = models.ManyToManyField("self", symmetrical=False)
此時,person對象如今就可使用person_set屬性進行反向查詢。

5.through
在使用ManyToManyField字段時,Django將自動生成一張表來管理多對多的關聯關係。

但咱們也能夠手動建立第三張表來管理多對多關係,此時就須要經過through來指定第三張表的表名。

6.through_fields
設置關聯的字段。

7.db_table
默認建立第三張表時,數據庫中表的名稱。
相關文章
相關標籤/搜索