Django——小結

課程介紹

MVC

MVC框架的核心思想是:解耦,讓不一樣的代碼塊之間下降耦合,加強代碼的可擴展性和可移植性,實現向後兼容javascript

  • M:Model,主要封裝對數據庫層的訪問,對數據庫中的數據進行增、刪、改、查操做
  • V:View,用於封裝結果,生成頁面展現的html內容
  • C:Controller,用於接收請求,處理業務邏輯,與Model和View交互,返回結果

Django-MVT

  • M:Model,與MVC中的M功能相同,負責和數據庫交互,進行數據處理
  • V:View,與MVC中的C功能相同,接收請求,進行業務處理,返回應答
  • T:Template,與MVC中的V功能相同,負責封裝構造要返回的html

MVVM

  • 出現緣由:因爲前端開發混合了HTML、CSS和JavaScript,並且頁面衆多,因此,代碼的組織和維護難度其實更加複雜
  • 好處:改變JavaScript對象的狀態,會致使DOM結構做出對應的變化,關注點就從如何操做DOM變成了如何更新JavaScript對象的狀態
  • MVVM的設計思想:關注Model的變化,讓MVVM框架去自動更新DOM的狀態,從而把開發者從操做DOM的繁瑣步驟中解脫出來
  • 結構:借鑑桌面應用程序的MVC思想,在前端頁面中,把Model用純JavaScript對象表示,View負責顯示,二者作到了最大限度的分離
  • 使用:把Model和View關聯起來的就是ViewModel。ViewModel負責把Model的數據同步到View顯示出來,還負責把View的修改同步回Model

入門

設計模型

ORM框架

  • O是object,也就類對象的意思
  • R是relation,翻譯成中文是關係,也就是關係數據庫中數據表的意思
  • M是mapping,是映射的意思

在ORM框架中,它幫咱們把類和數據表進行了一個映射,可讓咱們經過類和類對象就能操做它所對應的表格中的數據。ORM框架還有一個功能,它能夠根據咱們設計的類自動幫咱們生成數據庫中的表格,省去了咱們本身建表的過程css

  • 使用django進行數據庫開發的步驟以下
    • 在models.py中定義模型類
    • 遷移
    • 經過類和對象完成數據增刪改查操做

說明:不須要定義主鍵列,在生成時會自動添加,而且值爲自動增加html

數據表的默認名稱爲:<app_name>_<model_name>前端

一對多的關係(ForeignKey)應定義在多的那個類中java

管理站點

註冊模型類

登陸後臺管理後,默認沒有咱們建立的應用中定義的模型類,須要在本身應用中的admin.py文件中註冊,才能夠在後臺管理中看到,並進行增刪改查操做python

自定義管理頁面

Django提供了自定義管理頁面的功能,好比列表頁要顯示哪些值mysql

  • /admin.py文件代碼以下
 1 from django.contrib import admin
 2 from booktest.models import BookInfo,HeroInfo
 3 
 4 class BookInfoAdmin(admin.ModelAdmin):
 5     list_display = ['id', 'btitle', 'bpub_date']
 6 class HeroInfoAdmin(admin.ModelAdmin):
 7     list_display = ['id', 'hname','hgender','hcomment']
 8 
 9 admin.site.register(BookInfo,BookInfoAdmin)
10 admin.site.register(HeroInfo,HeroInfoAdmin)

 

模型

數據庫鏈接

/settings.py文件,找到DATABASES項,默認使用SQLite3數據庫jquery

修改成使用MySQL數據庫,代碼以下: 將引擎改成mysql,提供鏈接的主機HOST、端口PORT、數據庫名NAME、用戶名USER、密碼PASSWORD
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2', #數據庫名字,
        'USER': 'root', #數據庫登陸用戶名
        'PASSWORD': 'mysql', #數據庫登陸密碼
        'HOST': 'localhost', #數據庫所在主機
        'PORT': '3306', #數據庫端口
    }
}

  

注意:數據庫test2 Django框架不會自動生成,須要咱們本身進入mysql數據庫去建立git

模型類

字段類型

使用時須要引入django.db.models包,字段類型以下:正則表達式

    AutoField:自動增加的IntegerField,一般不用指定,不指定時Django會自動建立屬性名爲id的自動增加屬性。
    BooleanField:布爾字段,值爲True或False。
    NullBooleanField:支持Null、True、False三種值。
    CharField(max_length=字符長度):字符串。
        參數max_length表示最大字符個數。
    TextField:大文本字段,通常超過4000個字符時使用。
    IntegerField:整數。
    DecimalField(max_digits=None, decimal_places=None):十進制浮點數。
        參數max_digits表示總位數。
        參數decimal_places表示小數位數。
    FloatField:浮點數。
    DateField[auto_now=False, auto_now_add=False]):日期。
        參數auto_now表示每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,默認爲false。
        參數auto_now_add表示當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false。
        參數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤。
    TimeField:時間,參數同DateField。
    DateTimeField:日期時間,參數同DateField。
    FileField:上傳文件字段。
    ImageField:繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片。

  

選項

經過選項實現對字段的約束,選項以下:

    null:若是爲True,表示容許爲空,默認值是False。
    blank:若是爲True,則該字段容許爲空白,默認值是False。
    對比:null是數據庫範疇的概念,blank是表單驗證範疇的。
    db_column:字段的名稱,若是未指定,則使用屬性的名稱。
    db_index:若值爲True, 則在表中會爲此字段建立索引,默認值是False。
    default:默認值。
    primary_key:若爲True,則該字段會成爲模型的主鍵字段,默認值是False,通常做爲AutoField的選項使用。
    unique:若是爲True, 這個字段在表中必須有惟一值,默認值是False。

  

條件查詢

條件運算符

查詢等

1 list=BookInfo.objects.filter(id__exact=1)
2 可簡寫爲:
3 list=BookInfo.objects.filter(id=1)

模糊查詢

說明:若是要包含%無需轉義,直接寫便可

  • contains:是否包含
list = BookInfo.objects.filter(btitle__contains='')
  • startswith、endswith:以指定值開頭或結尾
1 list = BookInfo.objects.filter(btitle__endswith='')

以上運算符都區分大小寫,在這些運算符前加上i表示不區分大小寫,如iexact、icontains、istartswith、iendswith

空查詢

  • isnull:是否爲null
list = BookInfo.objects.filter(btitle__isnull=False)

範圍查詢

  • in:是否包含在範圍內
1 list = BookInfo.objects.filter(id__in=[1, 3, 5])

比較查詢

  • gt、gte、lt、lte:大於、大於等於、小於、小於等於
list = BookInfo.objects.filter(id__gt=3)
  • 不等於的運算符,使用exclude()過濾器
1 list = BookInfo.objects.exclude(id=3)

日期查詢

  • year、month、day、week_day、hour、minute、second:對日期時間類型的屬性進行運算
list = BookInfo.objects.filter(bpub_date__year=1980)
list = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))

F對象

兩個屬性比較使用F對象

1 list = BookInfo.objects.filter(bread__gte=F('bcomment'))
2 list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)

Q對象

多個過濾器逐個調用表示邏輯與關係,同sql語句中where部分的and關鍵字

1 list=BookInfo.objects.filter(bread__gt=20,id__lt=3)
2 3 list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)
4 
5 list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))
6 
7 Q對象前可使用~操做符,表示非not
8 list = BookInfo.objects.filter(~Q(pk=3))

聚合函數

使用aggregate()過濾器調用聚合函數。聚合函數包括:Avg,Count,Max,Min,Sum,被定義在django.db.models中

list = BookInfo.objects.aggregate(Sum('bread'))

注意aggregate的返回值是一個字典類型,格式以下:

{'聚合類小寫__屬性名':值} 如:{'sum__bread':3} 

使用count時通常不使用aggregate()過濾器,count函數的返回值是一個數字

list = BookInfo.objects.count()

查詢集

返回查詢集的過濾器

all():返回全部數據。
filter():返回知足條件的數據。
exclude():返回知足條件以外的數據,至關於sql語句中where部分的not關鍵字。
order_by():對結果進行排序

返回單個值的過濾器

    get():返回單個知足條件的對象
        若是未找到會引起"模型類.DoesNotExist"異常。
        若是多條被返回,會引起"模型類.MultipleObjectsReturned"異常。
    count():返回當前查詢結果的總條數。
    aggregate():聚合,返回一個字典。

判斷某一個查詢集中是否有數據

exists():判斷查詢集中是否有數據,若是有則返回True,沒有則返回False 

兩大特性

惰性執行:建立查詢集不會訪問數據庫,直到調用數據時,纔會訪問數據庫,調用數據的狀況包括迭代、序列化、與if合用。 緩存:使用同一個查詢集,第一次使用時會發生數據庫的查詢,而後把結果緩存下來,再次使用這個查詢集時會使用緩存的數據 

查詢集的緩存

每一個查詢集都包含一個緩存來最小化對數據庫的訪問。 在新建的查詢集中,緩存爲空,首次對查詢集求值時,會發生數據庫查詢,django會將查詢的結果存在查詢集的緩存中,並返回請求的結果,接下來對查詢集求值將重用緩存中的結果。 

限制查詢集

能夠對查詢集進行取下標或切片操做,等同於sql中的limit和offset子句。

    注意:不支持負數索引。

對查詢集進行切片後返回一個新的查詢集,不會當即執行查詢。

若是獲取一個對象,直接使用[0],等同於[0:1].get(),可是若是沒有數據,[0]引起IndexError異常,[0:1].get()若是沒有數據引起DoesNotExist異常。

示例:獲取第一、2項,運行查看。

list=BookInfo.objects.all()[0:2]

  

模型類擴展

元選項

#定義圖書模型類BookInfo
class BookInfo(models.Model):
    ...

    #定義元選項
    class Meta:
      db_table='bookinfo' #指定BookInfo生成的數據表名爲bookinfo

視圖

URLconf

位置參數

1 url(r'^delete(\d+)/$',views.show_arg)
2 def show_arg(request,id):
3     return HttpResponse('show arg %s'%id)

 

關鍵字參數

1 url(r'^delete(?P<id1>\d+)/$',views.show_arg)
2 def show_arg(request,id1):
3     return HttpResponse('show %s'%id1)

 

HttpRequest對象

屬性

下面除非特別說明,屬性都是隻讀的

path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分。
method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'。

    在瀏覽器中給出地址發出請求採用get方式,如超連接。
    在瀏覽器中點擊表單的提交按鈕發起請求,若是表單的method設置爲post則爲post請求。

encoding:一個字符串,表示提交的數據的編碼方式。

    若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8。
    這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。

GET:QueryDict類型對象,相似於字典,包含get請求方式的全部參數。
POST:QueryDict類型對象,相似於字典,包含post請求方式的全部參數。
FILES:一個相似於字典的對象,包含全部的上傳文件。
COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串。
session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見"狀態保持"。

  

HttpResponse對象

屬性

    content:表示返回的內容。
    charset:表示response採用的編碼字符集,默認爲utf-8。
    status_code:返回的HTTP響應狀態碼。
    content-type:指定返回數據的的MIME類型,默認爲'text/html'。

  

方法

    _init_:建立HttpResponse對象後完成返回內容的初始化。
    set_cookie:設置Cookie信息。

    set_cookie(key, value='', max_age=None, expires=None)

    cookie是網站以鍵值對格式存儲在瀏覽器中的一段純文本信息,用於實現用戶跟蹤。
        max_age是一個整數,表示在指定秒數後過時。
        expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過時。
        max_age與expires二選一。
        若是不指定過時時間,在關閉瀏覽器時cookie會過時。
    delete_cookie(key):刪除指定的key的Cookie,若是key不存在則什麼也不發生。
    write:向響應體中寫數據。

  

狀態保持

  • 瀏覽器請求服務器是無狀態的。
  • 無狀態指一次用戶請求時,瀏覽器、服務器沒法知道以前這個用戶作過什麼,每次請求都是一次新的請求。
  • 無狀態的應用層面的緣由是:瀏覽器和服務器之間的通訊都遵照HTTP協議。
  • 根本緣由是:瀏覽器與服務器是使用Socket套接字進行通訊的,服務器將請求結果返回給瀏覽器以後,會關閉當前的Socket鏈接,並且服務器也會在處理頁面完畢以後銷燬頁面對象

有時須要保存下來用戶瀏覽的狀態,好比用戶是否登陸過,瀏覽過哪些商品等。 實現狀態保持主要有兩種方式

  • 在客戶端存儲信息使用Cookie
  • 在服務器端存儲信息使用Session

狀態保持

  • 指某些網站爲了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據(一般通過加密)
  • Cookie是由服務器端生成,發送給User-Agent(通常是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置爲啓用cookie)
  • Cookie名稱和值能夠由服務器端開發本身定義,這樣服務器能夠知道該用戶是不是合法用戶以及是否須要從新登陸等
  • 服務器能夠利用Cookies包含信息的任意性來篩選並常常性維護這些信息,以判斷在HTTP傳輸中的狀態。Cookies最典型記住用戶名

Cookie的特色

  • Cookie以鍵值對的格式進行信息的存儲
  • Cookie基於域名安全,不一樣域名的Cookie是不能互相訪問的
  • 當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的全部Cookie信息提交給網站服務器

設置Cookie

response.set_cookie('h1', '你好')

 

讀取Cookie

response.write('<h1>' + request.COOKIES['h1'] + '</h1>')

 

Session

在服務器端進行狀態保持的方案就是Session

啓用Session

Django項目默認啓用Session

  • /settings.py文件,在項MIDDLEWARE_CLASSES中啓用Session中間件

存儲方式

/settings.py文件,設置SESSION_ENGINE項指定Session數據存儲的方式,能夠存儲在數據庫、緩存、Redis等

  • 存儲在數據庫中,以下設置能夠寫,也能夠不寫,這是默認存儲方式
SESSION_ENGINE='django.contrib.sessions.backends.db' 
  • 存儲在緩存中:存儲在本機內存中,若是丟失則不能找回,比數據庫的方式讀寫更快
SESSION_ENGINE='django.contrib.sessions.backends.cache' 
  • 混合存儲:優先從本機內存中存取,若是沒有則從數據庫中存取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db' 
  • 若是存儲在數據庫中,須要在項INSTALLED_APPS中安裝Session應用
  • 遷移後會在數據庫中建立出存儲Session的表
  • 由表結構可知,操做Session包括三個數據:鍵,值,過時時間

依賴於Cookie

全部請求者的Session都會存儲在服務器中,服務器如何區分請求者和Session數據的對應關係呢?

  • 在使用Session後,會在Cookie中存儲一個sessionid的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid後,會根據這個值找出這個請求者的Session

  • 結果:若是想使用Session,瀏覽器必須支持Cookie,不然就沒法使用Session了

  • 存儲Session時,鍵與Cookie中的sessionid相同,值是開發人員設置的鍵值對信息,進行了base64編碼,過時時間由開發人員設置

對象及方法

經過HttpRequest對象的session屬性進行會話的讀寫操做

  • 以鍵值對的格式寫session
request.session['鍵']=
  • 根據鍵讀取值
request.session.get('鍵',默認值) 
  • 清除全部session,在存儲中刪除值部分
request.session.clear() 
  • 清除session數據,在存儲中刪除session的整條數據
request.session.flush() 
  • 刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值
del request.session['鍵'] 
  • 設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時
設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時 
  • value
    • 若是value是一個整數,會話將在value秒沒有活動後過時
    • 若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時
    • 若是value爲None,那麼會話永不過時

使用Redis存儲Session

會話還支持文件、純cookie、Memcached、Redis等方式存儲

  • 安裝包
pip install django-redis-sessions==0.5.6 
  • /settings文件,增長以下項:
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 2
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'

 

模板

模板語言

標籤

  • for標籤語法以下:
    {%for item in 列表%}
    循環邏輯
    {{forloop.counter}}表示當前是第幾回循環,從1開始
    {%empty%}
    列表爲空或不存在時執行此邏輯
    {%endfor%}
    if標籤語法以下:
    {%if ...%}
    邏輯1
    {%elif ...%}
    邏輯2
    {%else%}
    邏輯3
    {%endif%}
    

      

過濾器

變量|過濾器:參數

  • 長度length,返回字符串包含字符的個數,或列表、元組、字典的元素個數
  • 默認值default,若是變量不存在時則返回默認值
data|default:'默認值' 

日期date,用於對日期類型的值進行字符串格式化,經常使用的格式化字符以下:

    Y表示年,格式爲4位,y表示兩位的年。
    m表示月,格式爲01,02,12等。
    d表示日, 格式爲01,02等。
    j表示日,格式爲1,2等。
    H表示時,24進制,h表示12進制的時。
    i表示分,爲0-59。
    s表示秒,爲0-59。

value|date:"Y年m月j日  H時i分s秒"

  

HTML轉義

關閉轉義

過濾器escape能夠實現對變量的html轉義,默認模板就會轉義,通常省略

{{t1|escape}}

過濾器safe:禁用轉義,告訴模板這個變量是安全的,能夠解釋執行

{{data|safe}}

標籤autoescape:設置一段代碼都禁用轉義,接受on、off參數

{%autoescape off%} ... {%endautoescape%}

CSRF

CSRF全拼爲Cross Site Request Forgery,譯爲跨站請求僞造。CSRF指攻擊者盜用了你的身份,以你的名義發送惡意請求

驗證碼

手動實現驗證碼

  • /views.py文件中,建立視圖verify_code
    • 隨機生成字符串後存入session中,用於後續判斷
    • 視圖返回mime-type爲image/png
 1 from PIL import Image, ImageDraw, ImageFont
 2 from django.utils.six import BytesIO
 3 ...
 4 def verify_code(request):
 5     #引入隨機函數模塊
 6     import random
 7     #定義變量,用於畫面的背景色、寬、高
 8     bgcolor = (random.randrange(20, 100), random.randrange(
 9         20, 100), 255)
10     width = 100
11     height = 25
12     #建立畫面對象
13     im = Image.new('RGB', (width, height), bgcolor)
14     #建立畫筆對象
15     draw = ImageDraw.Draw(im)
16     #調用畫筆的point()函數繪製噪點
17     for i in range(0, 100):
18         xy = (random.randrange(0, width), random.randrange(0, height))
19         fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
20         draw.point(xy, fill=fill)
21     #定義驗證碼的備選值
22     str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
23     #隨機選取4個值做爲驗證碼
24     rand_str = ''
25     for i in range(0, 4):
26         rand_str += str1[random.randrange(0, len(str1))]
27     #構造字體對象,ubuntu的字體路徑爲「/usr/share/fonts/truetype/freefont」
28     font = ImageFont.truetype('FreeMono.ttf', 23)
29     #構造字體顏色
30     fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
31     #繪製4個字
32     draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
33     draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
34     draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
35     draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
36     #釋放畫筆
37     del draw
38     #存入session,用於作進一步驗證
39     request.session['verifycode'] = rand_str
40     #內存文件操做
41     buf = BytesIO()
42     #將圖片保存在內存中,文件類型爲png
43     im.save(buf, 'png')
44     #將內存中的圖片數據返回給客戶端,MIME類型爲圖片png
45     return HttpResponse(buf.getvalue(), 'image/png')

 

驗證

  • /views.py文件中,建立視圖verify_yz
1 def verify_yz(request):
2     yzm=request.POST.get('yzm')
3     verifycode=request.session['verifycode']
4     response=HttpResponse('no')
5     if yzm==verifycode:
6         response=HttpResponse('ok')
7     return response

 

換驗證碼

<script type="text/javascript" src="/static/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#change').css('cursor','pointer').click(function() {
            $('#yzm').attr('src',$('#yzm').attr('src')+1)
        });
    });
</script>
...
<img id="yzm" src="/verify_code/?1"/>
<span id="change">看不清,換一個</span>

 

反向解析

在定義url時,須要爲include定義namespace屬性,爲url定義name屬性,使用時,在模板中使用url標籤,在視圖中使用reverse函數,根據正則表達式動態生成地址,減輕後期維護成本

url(r'^',include('booktest.urls',namespace='booktest'))

 url(r'^fan2/$', views.fan2,name='fan2')
 
 反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a>
 
 return redirect(reverse('booktest:fan2'))

  

經常使用

靜態文件處理

  • /settings.py文件中定義靜態文件存放的物理目錄
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

 

分頁

Paginator類實例對象

方法_init_(列表,int):返回分頁對象,第一個參數爲列表數據,第二個參數爲每頁數據的條數。
屬性count:返回對象總數。
屬性num_pages:返回頁面總數。
屬性page_range:返回頁碼列表,從1開始,例如[1, 2, 3, 4]。
方法page(m):返回Page類實例對象,表示第m頁的數據,下標以1開始

  

Page類實例對象

    調用Paginator對象的page()方法返回Page對象,不須要手動構造。
    屬性object_list:返回當前頁對象的列表。
    屬性number:返回當前是第幾頁,從1開始。
    屬性paginator:當前頁對應的Paginator對象。
    方法has_next():若是有下一頁返回True。
    方法has_previous():若是有上一頁返回True。
    方法len():返回當前頁面對象的個數。

  

示例

  • /views.py文件中建立視圖page_test
 1 from django.core.paginator import Paginator
 2 from booktest.models import AreaInfo
 3 ...
 4 #參數pIndex表示:當前要顯示的頁碼
 5 def page_test(request,pIndex):
 6     #查詢全部的地區信息
 7     list1 = AreaInfo.objects.filter(aParent__isnull=True)
 8     #將地區信息按一頁10條進行分頁
 9     p = Paginator(list1, 10)
10     #若是當前沒有傳遞頁碼信息,則認爲是第一頁,這樣寫是爲了請求第一頁時能夠不寫頁碼
11     if pIndex == '':
12         pIndex = '1'
13     #經過url匹配的參數都是字符串類型,轉換成int類型
14     pIndex = int(pIndex)
15     #獲取第pIndex頁的數據
16     list2 = p.page(pIndex)
17     #獲取全部的頁碼信息
18     plist = p.page_range
19     #將當前頁碼、當前頁的數據、頁碼信息傳遞到模板中
20     return render(request, 'booktest/page_test.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})

 

  • /urls.py文件中配置url
url(r'^page(?P<pIndex>[0-9]*)/$', views.page_test) 
  • 建立page_test.html模板文件
<html>
<head>
    <title>分頁</title>
</head>
<body>
顯示當前頁的地區信息:<br>
<ul>
{%for area in list%}
<li>{{area.id}}--{{area.atitle}}</li>
{%endfor%}
</ul>
<hr>
顯示頁碼信息:當前頁碼沒有連接,其它頁碼有連接<br>
{%for pindex in plist%}
    {%if pIndex == pindex%}
        {{pindex}}&nbsp;&nbsp;
    {%else%}
        <a href="/page{{pindex}}/">{{pindex}}</a>&nbsp;&nbsp;
    {%endif%}
{%endfor%}
</body>
</html>

 

示例:省市區選擇

 1 <html>
 2 <head>
 3     <title>省市區列表</title>
 4     <script type="text/javascript" src="/static/js/jquery-1.12.4.min.js"></script>
 5     <script type="text/javascript">
 6         $(function(){
 7             //頁面加載完成後獲取省信息,並添加到省select
 8             $.get('/area2/',function(dic) {
 9                 pro=$('#pro')
10                 $.each(dic.data,function(index,item){
11                     pro.append('<option value='+item[0]+'>'+item[1]+'</option>');
12                 })
13             });
14             //爲省select綁定change事件,獲取市信息,並添加到市select
15             $('#pro').change(function(){
16                 $.get('/area3_'+$(this).val()+'/',function(dic){
17                     city=$('#city');
18                     city.empty().append('<option value="">請選擇市</option>');
19                     dis=$('#dis');
20                     dis.empty().append('<option value="">請選擇區縣</option>');
21                     $.each(dic.data,function(index,item){
22                         city.append('<option value='+item[0]+'>'+item[1]+'</option>');
23                     })
24                 });
25             });
26             //爲市select綁定change事件,獲取區縣信息,並添加到區縣select
27             $('#city').change(function(){
28                 $.get('/area3_'+$(this).val()+'/',function(dic){
29                     dis=$('#dis');
30                     dis.empty().append('<option value="">請選擇區縣</option>');
31                     $.each(dic.data,function(index,item){
32                         dis.append('<option value='+item[0]+'>'+item[1]+'</option>');
33                     })
34                 })
35             });
36 
37         });
38     </script>
39 </head>
40 <body>
41 <select id="pro">
42     <option value="">請選擇省</option>
43 </select>
44 <select id="city">
45     <option value="">請選擇市</option>
46 </select>
47 <select id="dis">
48     <option value="">請選擇區縣</option>
49 </select>
50 </body>
51 </html

 

celery

情景:用戶發起request,並等待response返回。在本些views中,可能須要執行一段耗時的程序,那麼用戶就會等待很長時間,形成很差的用戶體驗,好比發送郵件、手機驗證碼等

celery名詞

  • 任務task:就是一個Python函數
  • 隊列queue:將須要執行的任務加入到隊列中
  • 工人worker:在一個新進程中,負責執行隊列中的任務
  • 代理人broker:負責調度,在佈置環境中使用redis
  1. /settings.py中安裝
INSTALLED_APPS = (
  ...
  'djcelery',
}

 

  1. /settings.py文件中配置代理和任務模塊
import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://127.0.0.1:6379/2'

 

  1. 建立tasks.py文件
1 import time
2 from celery import task
3 
4 @task
5 def sayhello():
6     print('hello ...')
7     time.sleep(2)
8     print('world ...')

 

  1. /views.py文件,修改sayhello視圖
1 from booktest import tasks
2 ...
3 def sayhello(request):
4     # print('hello ...')
5     # time.sleep(2)
6     # print('world ...')
7     tasks.sayhello.delay()
8     return HttpResponse("hello world")

 

  1. 執行遷移生成celery須要的數據表
  • python manage.py migrate
  1. 啓動Redis,若是已經啓動則不須要啓動
  • sudo service redis start
  1. 啓動worker
  • python manage.py celery worker --loglevel=info
  1. 修改成發送郵件的代碼,就能夠實現無阻塞發送郵件
 1 from django.conf import settings
 2 from django.core.mail import send_mail
 3 from celery import task
 4 
 5 @task
 6 def sayhello():
 7     msg='<a href="http://www.itcast.cn/subject/pythonzly/index.shtml" target="_blank">點擊激活</a>'
 8     send_mail('註冊激活','',settings.EMAIL_FROM,
 9               ['itcast88@163.com'],
10               html_message=msg)

 

請使用手機"掃一掃"x

相關文章
相關標籤/搜索