Django框架之經常使用知識

經常使用

三大塊除了M、V、T,接下來學習一些其它的知識點,這些知識點不在三大塊範圍內,Django提供了這些功能後,能夠幫助咱們更快更好的完成開發。javascript

主要知識點以下:css

  • 靜態文件處理
  • 中間件
  • 上傳圖片
  • Admin站點
  • 分頁
  • 示例:省市區選擇,jquery,ajax

 

 

靜態文件

項目中的CSS、圖片、js都是靜態文件。通常會將靜態文件放到一個單獨的目錄中,以方便管理。在html頁面中調用時,也須要指定靜態文件的路徑,Django中提供了一種解析的方式配置靜態文件路徑。靜態文件能夠放在項目根目錄下,也能夠放在應用的目錄下,因爲有些靜態文件在項目中是通用的,因此推薦放在項目的根目錄下,方便管理。html

示例

1)在test5/settings.py文件中定義靜態文件存放的物理目錄。java

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

2)在項目根目錄下建立static目錄,再建立img、css、js目錄。python

3)在booktest/views.py中定義視圖static_test。jquery

def static_test(request):
    return render(request,'booktest/static_test.html')

4)在booktest/urls.py中配置url。ajax

  url(r'^static_test/$',views.static_test),

5)在templates/booktest/下建立static_test.html文件。數據庫

<html>
<head>
    <title>靜態文件</title>
</head>
<body>
<img src="/static/img/sg.png"/>
</body>
</html>

6)保存圖片到static/img/目錄下,名稱爲sg.png。django

 

爲了安全能夠經過配置項隱藏真實圖片路徑,在模板中寫成固定路徑,後期維護太麻煩,能夠使用static標籤,根據配置項生成靜態文件路徑。瀏覽器

1)修改templates/booktest/static_test.html以下:

<html>
<head>
    <title>靜態文件</title>
</head>
<body>
修改前:<img src="/static/img/sg.png"/>
<hr>
修改後:<img src="/abc/img/sg.png"/>
<hr>
動態配置:
{%load static from staticfiles%}
<img src="{%static "img/sg.png" %}"/>
</body>
</html>

 

 

 

中間件

Django中的中間件是一個輕量級、底層的插件系統,能夠介入Django的請求和響應處理過程,修改Django的輸入或輸出。中間件的設計爲開發者提供了一種無侵入式的開發方式,加強了Django框架的健壯性,其它的MVC框架也有這個功能,名稱爲IoC。

Django在中間件中預置了五個方法,這五個方法的區別在於不一樣的階段執行,對輸入或輸出進行干預,方法以下:

1)初始化:無需任何參數,服務器響應第一個請求的時候調用一次,用於肯定是否啓用當前中間件。

def __init__(self):
    pass

2)處理請求前:在每一個請求上,request對象產生以後,url匹配以前調用,返回None或HttpResponse對象。

def process_request(self, request):
    pass

3)處理視圖前:在每一個請求上,url匹配以後,視圖函數調用以前調用,返回None或HttpResponse對象。

def process_view(self, request, view_func, *view_args, **view_kwargs):
    pass

4)處理響應後:視圖函數調用以後,全部響應返回瀏覽器以前被調用,在每一個請求上調用,返回HttpResponse對象。

def process_response(self, request, response):
    pass

5)異常處理:當視圖拋出異常時調用,在每一個請求上調用,返回一個HttpResponse對象。

def process_exception(self, request,exception):
    pass

示例

中間件是一個獨立的python類,,能夠定義這五個方法中的一個或多個。

1)在booktest/目錄下建立middleware.py文件,代碼以下:

class my_mid:
    def __init__(self):
        print '--------------init'

    def process_request(self,request):
        print '--------------request'

    def process_view(self,request, view_func, *view_args, **view_kwargs):
        print '--------------view'

    def process_response(self,request, response):
        print '--------------response'
        return response

2)在test5/settings.py文件中,向MIDDLEWARE_CLASSES項中註冊。

3)修改booktest/views.py中視圖index。

def index(request):
    print '======index======'
    return render(request,'booktest/index.html')

4)運行服務器,命令行中效果以下圖:

3)刷新頁面,命令行中效果以下圖:

異常中間件

1)在booktest/middleware.py中定義兩個異常類以下:

class exp1:
    def process_exception(self,request,exception):
        print '--------------exp1'
class exp2:
    def process_exception(self,request,exception):
        print '--------------exp2'

2)在test5/settings.py文件中,向MIDDLEWARE_CLASSES項中註冊。

3)修改booktest/views.py中視圖index。

def index(request):
    print '======index======'
    raise Exception('自定義異常')
    return render(request,'booktest/index.html')

總結:若是多個註冊的中間件類中都有process_exception的方法,則先註冊的後執行

 

 

 

Admin站點

內容發佈的部分由網站的管理員負責查看、添加、修改、刪除數據,開發這些重複的功能是一件單調乏味、缺少創造力的工做,爲此,Django可以根據定義的模型類自動地生成管理模塊。

在第一部分對管理站點作了簡單介紹,如今作詳細講解。在Django項目中默認啓用Admin管理站點。

1)準備工做:建立管理員的用戶名和密碼。

python manage.py createsuperuser

按提示填寫用戶名、郵箱、密碼。

2)使用:在應用的admin.py中註冊模型類

例:打開booktest/admin.py文件,註冊地區模型。

from django.contrib import admin
from booktest.models import *

admin.site.register(AreaInfo)

3)輸入以下網址:

登陸成功後,能夠看到AreaInfos,能夠進行增長、修改、刪除、查詢的管理。

列表頁顯示效果以下圖:

 

 

控制管理頁展現

類ModelAdmin能夠控制模型在Admin界面中的展現方式,主要包括在列表頁的展現方式、添加修改頁的展現方式。

1)在booktest/admin.py中,註冊模型類前定義管理類AreaAdmin。

class AreaAdmin(admin.ModelAdmin):
    pass

管理類有兩種使用方式:

  • 註冊參數
  • 裝飾器

註冊參數:打開booktest/admin.py文件,註冊模型類代碼以下:

admin.site.register(AreaInfo,AreaAdmin)

裝飾器:打開booktest/admin.py文件,在管理類上註冊模型類,代碼以下:

@admin.register(AreaInfo)
class AreaAdmin(admin.ModelAdmin):
    pass

接下來介紹如何控制列表頁、增長修改頁展現效果。

 

列表頁選項

頁大小

每頁中顯示多少條數據,默認爲每頁顯示100條數據,屬性以下:

list_per_page=100

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    list_per_page = 10

2)在瀏覽器中查看區域信息的列表頁面,效果以下圖:

"操做選項"的位置

頂部顯示的屬性,設置爲True在頂部顯示,設置爲False不在頂部顯示,默認爲True。

actions_on_top=True

底部顯示的屬性,設置爲True在底部顯示,設置爲False不在底部顯示,默認爲False。

actions_on_bottom=False

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    actions_on_top = True
    actions_on_bottom = True

2)在瀏覽器中刷新效果以下圖:

列表中的列

屬性以下:

list_display=[模型字段1,模型字段2,...]

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle']

2)在瀏覽器中刷新效果以下圖:

點擊列頭能夠進行升序或降序排列。

將方法做爲列

列能夠是模型字段,還能夠是模型方法,要求方法有返回值。

1)打開booktest/models.py文件,修改AreaInfo類以下:

class AreaInfo(models.Model):
    ...
    def title(self):
        return self.atitle

2)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle','title']

3)在瀏覽器中刷新效果以下圖:

 

 方法列是不能排序的,若是須要排序須要爲方法指定排序依據。

admin_order_field=模型類字段

1)打開booktest/models.py文件,修改AreaInfo類以下:

class AreaInfo(models.Model):
    ...
    def title(self):
        return self.atitle
    title.admin_order_field='atitle'

2)在瀏覽器中刷新效果以下圖:

 

 

列標題

列標題默認爲屬性或方法的名稱,能夠經過屬性設置。須要先將模型字段封裝成方法,再對方法使用這個屬性,模型字段不能直接使用這個屬性。

short_description='列標題'

1)打開booktest/models.py文件,修改AreaInfo類以下:

class AreaInfo(models.Model):
    ...
    title.short_description='區域名稱'

2)在瀏覽器中刷新效果以下圖:

關聯對象

沒法直接訪問關聯對象的屬性或方法,能夠在模型類中封裝方法,訪問關聯對象的成員。

1)打開booktest/models.py文件,修改AreaInfo類以下:

class AreaInfo(models.Model):
    ...
    def parent(self):
        if self.aParent is None:
          return ''
        return self.aParent.atitle
    parent.short_description='父級區域名稱'

2)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle','title','parent']

3)在瀏覽器中刷新效果以下圖:

 

右側欄過濾器

屬性以下,只能接收字段,會將對應字段的值列出來,用於快速過濾。通常用於有重複值的字段

list_filter=[]

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_filter=['atitle']

2)在瀏覽器中刷新效果以下圖:

搜索框

屬性以下,用於對指定字段的值進行搜索,支持模糊查詢。列表類型,表示在這些字段上進行搜索。

search_fields=[]

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    search_fields=['atitle']

2)在瀏覽器中刷新效果以下圖:

中文標題

1)打開booktest/models.py文件,修改模型類,爲屬性指定verbose_name參數,即第一個參數

class AreaInfo(models.Model):
    atitle=models.CharField('標題',max_length=30)#名稱
    ...

2)在瀏覽器中刷新效果以下圖:

 

 

編輯頁選項

顯示字段順序

屬性以下:

fields=[]

1)點擊某行ID的連接,能夠轉到修改頁面,默認效果以下圖:

2)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    fields=['aParent','atitle']

3)刷新瀏覽器效果以下圖:

在下拉列表中輸出的是對象的名稱,能夠在模型類中定義str方法用於對象轉換字符串。

1)打開booktest/models.py文件,修改AreaInfo類,添加str方法。

class AreaInfo(models.Model):
    ...
    def __str__(self):
        return self.atitle

2)刷新瀏覽器效果以下圖:

 

 

分組顯示

屬性以下:

fieldset=(
    ('組1標題',{'fields':('字段1','字段2')}),
    ('組2標題',{'fields':('字段3','字段4')}),
)

1)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    # fields=['aParent','atitle']
    fieldsets = (
        ('基本', {'fields': ['atitle']}),
        ('高級', {'fields': ['aParent']})
    )

2)刷新瀏覽器效果以下圖:

關聯對象

在一對多的關係中,能夠在一端的編輯頁面中編輯多端的對象,嵌入多端對象的方式包括表格、塊兩種。 類型InlineModelAdmin:表示在模型的編輯頁面嵌入關聯模型的編輯。子類TabularInline:以表格的形式嵌入。子類StackedInline:以塊的形式嵌入。

1)打開booktest/admin.py文件,建立AreaStackedInline類。

class AreaStackedInline(admin.StackedInline):
    model = AreaInfo#關聯子對象
    extra = 2#額外編輯2個子對象

2)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    inlines = [AreaStackedInline]

3)刷新瀏覽器效果以下圖:

 

 

能夠用表格的形式嵌入。

1)打開booktest/admin.py文件,建立AreaTabularInline類。

class AreaTabularInline(admin.TabularInline):
    model = AreaInfo#關聯子對象
    extra = 2#額外編輯2個子對象

2)打開booktest/admin.py文件,修改AreaAdmin類以下:

class AreaAdmin(admin.ModelAdmin):
    ...
    inlines = [AreaTabularInline]

3)刷新瀏覽器效果以下圖:

 

 

 

上傳圖片

在python中進行圖片操做,須要安裝包PIL。

pip install Pillow==3.4.1

在Django中上傳圖片包括兩種方式:

  • 在管理頁面admin中上傳圖片
  • 自定義form表單中上傳圖片

上傳圖片後,將圖片存儲在服務器上,而後將圖片的路徑存儲在表中。

建立包含圖片的模型類

將模型類的屬性定義成models.ImageField類型。

1)打開booktest/models.py文件,定義模型類PicTest。

class PicTest(models.Model):
    pic = models.ImageField(upload_to='booktest/')

2)回到命令行中,生成遷移。

python manage.py makemigrations

3)打開booktest/migrations/0001_initial.py文件,刪除AreaInfo部分,由於這個表已經存在。

4)回到命令行中,執行遷移。

python manage.py migrate

5)由於當前沒有定義圖書、英雄模型類,會提示「是否刪除」,輸入「no」後回車,表示不刪除。

6)打開test5/settings.py文件,設置圖片保存路徑。

由於圖片也屬於靜態文件,因此保存到static目錄下。

MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")

 

在管理頁面admin中上傳圖片

1)打開booktest/admin.py文件,註冊PicTest。

from django.contrib import admin
from booktest.models import *

admin.site.register(PicTest)

2)運行服務器,輸入以下網址。

3)點擊「Add」添加數據,打開新頁面。

4)選擇圖片,點擊「save」按鈕完成圖片上傳。 5)回到數據庫命令行,查詢表pictest中的數據以下圖:

 

 

自定義form表單中上傳圖片

1)打開booktest/views.py文件,建立視圖pic_upload。

def pic_upload(request):
    return render(request,'booktest/pic_upload.html')

2)打開booktest/urls.py文件,配置url。

 url(r'^pic_upload/$', views.pic_upload),

3)在templates/booktest/目錄下建立模板pic_upload.html。

在模板中定義上傳表單,要求以下:

  • form的屬性enctype="multipart/form-data"
  • form的method爲post
  • input的類型爲file
<html>
<head>
    <title>自定義上傳圖片</title>
</head>
<body>
    <form method="post" action="/pic_handle/" enctype="multipart/form-data">
        {%csrf_token%}
        <input type="file" name="pic"/><br>
        <input type="submit" value="上傳">
    </form>
</body>
</html>

4)打開booktest/views.py文件,建立視圖pic_handle,用於接收表單保存圖片。

request對象的FILES屬性用於接收請求的文件,包括圖片。

from django.conf import settings
from django.http import HttpResponse
...
def pic_handle(request):
    f1=request.FILES.get('pic')
    fname='%s/booktest/%s'%(settings.MEDIA_ROOT,f1.name)
    with open(fname,'wb') as pic:
        for c in f1.chunks():
            pic.write(c)
    return HttpResponse('OK')

5)打開booktest/urls.py文件,配置url。

  url(r'^pic_handle/$', views.pic_handle),

6)運行服務器

選擇文件後點擊按鈕上傳圖片。

 

 

 

分頁

Django提供了數據分頁的類,這些類被定義在django/core/paginator.py中。 類Paginator用於對列進行一頁n條數據的分頁運算。類Page用於表示第m頁的數據。

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():返回當前頁面對象的個數。

示例

1)在booktest/views.py文件中建立視圖page_test。

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

2)在booktest/urls.py文件中配置url

  url(r'^page(?P<pIndex>[0-9]*)/$', views.page_test),

3)在templates/booktest/目錄下建立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>

4)運行服務器

5)點擊頁碼數字,效果以下圖:

 

 

 

示例:省市區選擇

本示例講解在Django中使用jquery的ajax進行數據交互。 jquery框架中提供了$.ajax、$.get、$.post方法,用於進行異步交互,因爲Django中默認使用CSRF約束,推薦使用$.get。

示例:實現省市區的選擇。

最終實現效果如圖:

1)將jquery文件拷貝到static/js/目錄下。

2)打開booktest/views.py文件,定義視圖area1,用於顯示下拉列表。

#提供顯示下拉列表的控件,供用戶操做
def area1(request):
    return render(request,'booktest/area1.html')

3)打開booktest/urls.py文件,配置url。

  url(r'^area1/$', views.area1),

4)在templates/booktest/目錄下建立area1.html。

<html>
<head>
    <title>省市區列表</title>
    <script type="text/javascript" src="/static/js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript">
        $(function(){
            //頁面加載完成後獲取省信息,並添加到省select
            $.get('/area2/',function(dic) {
                pro=$('#pro')
                $.each(dic.data,function(index,item){
                    pro.append('<option value='+item[0]+'>'+item[1]+'</option>');
                })
            });
            //爲省select綁定change事件,獲取市信息,並添加到市select
            $('#pro').change(function(){
                $.get('/area3_'+$(this).val()+'/',function(dic){
                    city=$('#city');
                    city.empty().append('<option value="">請選擇市</option>');
                    dis=$('#dis');
                    dis.empty().append('<option value="">請選擇區縣</option>');
                    $.each(dic.data,function(index,item){
                        city.append('<option value='+item[0]+'>'+item[1]+'</option>');
                    })
                });
            });
            //爲市select綁定change事件,獲取區縣信息,並添加到區縣select
            $('#city').change(function(){
                $.get('/area3_'+$(this).val()+'/',function(dic){
                    dis=$('#dis');
                    dis.empty().append('<option value="">請選擇區縣</option>');
                    $.each(dic.data,function(index,item){
                        dis.append('<option value='+item[0]+'>'+item[1]+'</option>');
                    })
                })
            });

        });
    </script>
</head>
<body>
<select id="pro">
    <option value="">請選擇省</option>
</select>
<select id="city">
    <option value="">請選擇市</option>
</select>
<select id="dis">
    <option value="">請選擇區縣</option>
</select>
</body>
</html>

5)運行服務器瀏覽效果以下圖:

6)打開booktest/views.py文件,定義視圖area2,用於獲取省信息。

from django.http import JsonResponse
...
#獲取省信息
def area2(request):
    list = AreaInfo.objects.filter(aParent__isnull=True)
    list2 = []
    for item in list:
        list2.append([item.id, item.atitle])
    return JsonResponse({'data': list2})

7)打開booktest/urls.py文件,配置url。

  url(r'^area2/$', views.area2),

8)在瀏覽器中輸入網址,瀏覽效果以下圖:

9)打開booktest/views.py文件,定義視圖area3,用於根據編號獲取對應的子級信息,若是傳遞的是省編號則獲取市信息,若是傳遞的是市編號則獲取區縣信息。

#根據pid查詢子級區域信息
def area3(request, pid):
    list = AreaInfo.objects.filter(aParent_id=pid)
    list2 = []
    for item in list:
        list2.append([item.id, item.atitle])
    return JsonResponse({'data': list2})

10)打開booktest/urls.py文件,配置url。

 url(r'^area3_(\d+)/$', views.area3),

11)在瀏覽器中輸入以下網址,瀏覽效果以下圖:

12)在瀏覽器中輸入以下網址,選擇效果以下圖:

相關文章
相關標籤/搜索