那些年咱們一塊兒玩的Django框架之全面講解

Web框架之Django:

(1)簡介:

Django是一個由Python寫成開源的重量級Web應用框架,採用MTV的框架模式。它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容爲主的網站的,便是CMS(內容管理系統)軟件。並於2005年7月在BSD許可證下發布。這套框架是以比利時的吉普賽爵士吉他手Django Reinhardt來命名的。Django的優點在於:大而全,框架自己集成了ORM、模型綁定、模板引擎、緩存、Session等諸多功能。javascript

(2)Django的處理流程:

blob.png

1.     當用戶發出HTTP請求,URLhandler接收用戶請求,根據開發人員設置的路由規則匹配相應的處理類html

2.     根據請求的類型判斷調用的HTTP方法java

3.     若是須要鏈接數據庫,Views中的函數將會調用Models的方法,不然直接去Template中取出HTML頁面直接返回python

4.     調用Models的時候,Models會去數據庫讀取數據再返回給Viewsmysql

5.     通過渲染頁面一塊兒將最終的HTML頁面返回給頁面jquery

☆MTV與MVC:

MTV和MVC的思想是同樣的的,只是思想的體現有所不一樣。git

MVC:M管理應用程序的狀態,並約束改變狀態的行爲,通常叫作業務規則;V負責把數據格式化後呈現給用戶查看;C接收用戶操做,根據訪問模型獲取數據,並調用視圖顯示這些數據,控制器(處理器)用於將模型與視圖隔離併成爲兩者之間的聯繫紐帶。ajax

MTV:M表明數據存取層,也就是Model,改爲處理與數據相關的全部事務如何存取,如何驗證數據的有效性,包含哪些行爲與數據相關;T指的是表現層,該層處理與現實相關的行爲,如何在頁面文檔中顯示數據,展示內容,也就是Template;V表明業務邏輯層,該層包含存取模型及調取恰當模板的相關邏輯。正則表達式

☆Django版的MTV:

Django也是一個MVC框架。可是在Django中,控制器接受用戶輸入的部分由框架自行處理,因此 Django 裏更關注的是模型(Model)、模板(Template)和視圖(Views),稱爲 MTV模式。sql

☆Django設計MVC優美哲學:

1.對象關係映射 (ORM,object-relational mapping):

以Python類形式定義你的數據模型,ORM將模型與關係數據庫鏈接起來,你將獲得一個很是容易使用的數據庫API,同時你也能夠在Django中使用原始的SQL語句。

2.URL 分派:

使用正則表達式匹配URL,你能夠設計任意的URL,沒有框架的特定限定。像你喜歡的同樣靈活。

3.模版系統:

使用Django強大而可擴展的模板語言,能夠分隔設計、內容和Python代碼。而且具備可繼承性。

4.表單處理:

你能夠方便的生成各類表單模型,實現表單的有效性檢驗。能夠方便的從你定義的模型實例生成相應的表單。

5.Cache系統:

能夠掛在內存緩衝或其它的框架實現超級緩衝一一實現你所須要的粒度。

6.會話(session):

用戶登陸與權限檢查,快速開發用戶會話功能。

7.國際化:

內置國際化系統,方便開發出多種語言的網站。

8.自動化的管理界面:

不須要你花大量的工做來建立人員管理和更新內容。Django自帶一個ADMIN site,相似於內容管理系統

(3)Django的經常使用命令:

django-admin startproject sitename  # 在當前目錄下建立一個Django程序

python manage.py runserver ip:port  # 啓動服務器,默認是127.0.0.1:8000

python manage.py startapp appname   # 建立APP

python manage.py syncdb# 同步數據庫,Django 1.7及以上版本須要用如下的命令:

python manage.py makemigrations # 建立數據配置文件,顯示並記錄全部數據的改動

python manage.py migrate  #建立表結構,將改動更新到數據庫

python manage.py createsuperuser  # 建立超級管理員

python manage.py dbshell  # 數據庫命令行

python manage.py  # 查看命令列表

(4)Django數據庫相關:

☆默認使用SQLite3數據庫的配置:

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.sqlite3',

        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

    }

}

☆MySQL的配置:

DATABASES = {

    'default': {

    'ENGINE': 'django.db.backends.mysql',

    'NAME':'',   # 數據庫應該以utf-8編碼以支持中文

    'USER': '',

    'PASSWORD': '',

    'HOST': '',

    'PORT': '',

    }

}

因爲Python開發經常使用Python3.x,Django鏈接數據庫的時候使用的是MySQL的MySQLdb模塊,然而在Python3中尚未此模塊,所以須要使用pymysql進行代替,下面的配置代碼寫入到項目目錄的__init__.py中便可:

import pymysql

pymysql.install_as_MySQLdb()

☆PostgreSQL數據庫的配置:

DATABASES = {

    'default': {

        'NAME': '',

        'ENGINE': 'django.db.backends.postgresql_psycopg2',

        'USER': '',

        'PASSWORD': ''

    }

☆Oracle數據庫的配置:

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.oracle',

        'NAME': '',

        'USER': 'r',

        'PASSWORD': '',

        'HOST': '',

        'PORT': '',

    }

}

Django框架對於開發者而言高度透明化,對於不一樣數據庫的具體使用方法是一致的,改變數據庫類型只須要變更上述配置便可。

☆Django中的Model數據庫操做:

Django提供了一個抽象層(「Model」)來構建和管理Web應用程序的數據。Django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。關係對象映射(Object Relational Mapping,簡稱ORM)。

建立Django項目後的目錄結構:

.

├── app0  # app應用目錄

   ├── admin.py

   ├── apps.py

   ├── __init__.py

   ├── migrations

   │   └── __init__.py

   ├── models.py

   ├── tests.py

   └── views.py

├── DjangoAllNotes  # 與項目同名的項目目錄

   ├── __init__.py

   ├── __pycache__

   │   ├── __init__.cpython-36.pyc

   │   └── settings.cpython-36.pyc

   ├── settings.py  # 公用的Django配置文件

   ├── urls.py

   └── wsgi.py

├── manage.py

└── template

★建立基本表結構:

在Django中,每一張數據表就是一個類,這些類存在於每一個app目錄的models.py文件中,執行 python manage.py makemigrations 會根據models.py生成配置文件,再執行 python manage.py migrate 將會鏈接數據庫並建立表結構。

# file:models.py

from django.db import models

 

# Create your models here.

class UserInfo(models.Model):

    username = models.CharField(max_length=32)

    password = models.CharField(max_length=64)

    age = models.IntegerField()

    email = models.EmailField()

    other = models.TextField()

執行命令:

D:\Codes\Python\DjangoAllNotes>python manage.py makemigrations

Migrations for 'app0':

  app0\migrations\0001_initial.py

    - Create model UserInfo

 

D:\Codes\Python\DjangoAllNotes>python manage.py migrate

Operations to perform:

  Apply all migrations: admin, app0, auth, contenttypes, sessions

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying app0.0001_initial... OK

  Applying contenttypes.0002_remove_content_type_name... OK

  Applying auth.0002_alter_permission_name_max_length... OK

  Applying auth.0003_alter_user_email_max_length... OK

  Applying auth.0004_alter_user_username_opts... OK

  Applying auth.0005_alter_user_last_login_null... OK

  Applying auth.0006_require_contenttypes_0002... OK

  Applying auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying sessions.0001_initial... OK

 

D:\Codes\Python\DjangoAllNotes>

可視化以下:

blob.png

其餘的字段參數:

1.null = True     # 數據庫字段是否能夠爲空

2.blank = True    # django Admin 中添加數據時是否可容許空值

3.primary_key = False # 主鍵,對AutoField設置主鍵後,就會代替原來的自增 id

4.auto_now         # 自動建立,不管添加或修改,都是當前操做的時間

5.auto_now_add  # 自動建立永遠是建立時的時間

6.選擇:

GENDER_CHOICE = (

(u'',u'Male'),

(u'',u'Female'),

)

gender = models.CharField(max_length=2,choices = GENDER_CHOICE)

7.max_length  # 長度,是CharField必須屬性

8.default  # 默認值

9.verbose_name  # Admin中字段的顯示名稱

10.name|db_column  # 數據庫中的字段名稱

11.unique = True   # 不容許重複

12.db_index = True  # 數據庫索引

13.editable = True   # Admin中是否能夠編輯

14.error_messages = None  # 錯誤提示

15.auto_created = False  # 自動建立

16.help_text # Admin中提示幫助信息

17.validators = []

18.upload-to

其餘的字段:

1.models.AutoField

自增列,int類型,若是沒有設置,默認會生成一個名稱爲id的列,若是要顯示一個自定義的自增列,必須將其設置爲主鍵

2.models.CharField

字符串字段,必須設置max_length屬性

3.models.BooleanField

布爾類型,在數據庫中的類型使用tinyint類型構造實現,不能爲空

4.models.ComaSeparatedIntegerField

用逗號分割的數字,在數據庫中是varchar類型,繼承自CharField,因此必須 max_lenght 屬性

5.models.DateField

日期類型,在數據庫中對應date類型,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。

6.models.DateTimeField

日期類型,在數據庫中對應datetimeauto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。

7.models.Decimal

十進制小數類型,在數據庫中對應decimal類型,必須指定整數位max_digits和小數位decimal_places

8.models.EmailField

字符串類型(正則表達式郵箱),在數據庫中對應varchar類型

9.models.FloatField

浮點類型,在數據庫中對應double類型

10.models.IntegerField 

整型,在數據庫中對應int類型

11.models.BigIntegerField 

長×××

12.integer_field_ranges = {

  'SmallIntegerField': (-32768, 32767),

  'IntegerField': (-2147483648, 2147483647),

  'BigIntegerField': (-9223372036854775808, 9223372036854775807),

  'PositiveSmallIntegerField': (0, 32767),

  'PositiveIntegerField': (0, 2147483647),

}

13.models.IPAddressField  

字符串類型(ip4正則表達式)

14.models.GenericIPAddressField  

字符串類型(ip4ip6是可選的),參數protocol能夠是:bothipv4ipv6,驗證時,會根據設置報錯

15.models.NullBooleanField  

容許爲空的布爾類型

16.models.PositiveIntegerFiel  

正數範圍的Integer

17.models.PositiveSmallIntegerField  

正數範圍的smallInteger

18.models.SlugField  

減號、下劃線、字母、數字

19.models.SmallIntegerField  

數字,數據庫中的字段有:tinyintsmallintintbigint

20.models.TextField  

字符串,在數據庫中對應longtext

21.models.TimeField  

時間 HH:MM[:ss[.uuuuuu]]

22.models.URLField  

字符串,地址正則表達式

23.models.BinaryField  

二進制

24.models.ImageField  

圖片

25.models.FilePathField

文件

元數據:

db_table = ‘TableName’# 數據庫中生成的名稱,使用app名稱+下劃線+類名

index_tohether = [(‘pub_date’,’deadline’)]  # 聯合索引

unique_together = ((‘drive’,’ restaurant’))  # 聯合惟一索引

verbose_name  admin中顯示的名稱

觸發Model中的驗證和錯誤提示有兩種方式:

1.DjangoAdmin中的錯誤信息會優先根據Admin內部的ModelForm錯誤信息提示,若是都成功,纔會再驗證Model的字段並顯示指定的錯誤信息。

更改Admin中的錯誤提示:

from django.contrib import admin

# Register your models here.

# file:admin.py

from django.contrib import admin

from app0 import models

from django import forms

class UserInfoForm(forms.ModelForm):

    username = forms.CharField(error_messages={'required': '用戶名不能爲空.'})

    email = forms.EmailField(error_messages={'invalid': '郵箱格式錯誤.'})

    age = forms.IntegerField(initial=1, error_messages={'required': '請輸入數值.', 'invalid': '年齡必須爲數值.'})

 

    class Meta:

        model = models.UserInfo

        fields = "__all__"

class UserInfoAdmin(admin.ModelAdmin):

    form = UserInfoForm

 

admin.site.register(models.UserInfo, UserInfoAdmin)

2.調用Model對象的clean_fields方法:

# file:models.py

class UserInfo(models.Model):

nid = models.AutoField(primary_key=True)

username = models.CharField(max_length=32)

email = models.EmailField(error_messages={'invalid': '格式錯.'})

# file:views.py

def index(request):

   obj = models.UserInfo(username='11234', email='uu')

   try:

       print(obj.clean_fields())

   except Exception as e:

       print(e)

return HttpResponse('ok')

# Modelclean方法是一個鉤子,可用於定製操做,如:上述的異常處理。

★連表操做:

一對多:models.ForeignKey(其餘表)

多對多:models.ManyToManyField(其餘表)

一對一:models.OneToOneField(其餘表)

1.一對多:

ForeignKey(ForeignObject) # ForeignObject(RelatedField)

to,                            # 要進行關聯的表名

to_field=None,               # 要關聯的表中的字段名稱

on_delete=None,              # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲

- 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(可執行對象)

一對一:

OneToOneField(ForeignKey)

to,                         # 要進行關聯的表名

to_field=None               # 要關聯的表中的字段名稱

on_delete=None,             # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲

一對一其實就是 一對多 + 惟一索引,當兩個類之間有繼承關係時,默認會建立一個一對一字段。

多對多:

ManyToManyField(RelatedField)

to,                         # 要進行關聯的表名

related_name=None,          # 反向操做時,使用的字段名,用於代替 【表名_set 如: obj.表名_set.all()

related_query_name=None,    # 反向操做時,使用的鏈接前綴,用於替換【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to=None,      # AdminModelForm中顯示關聯數據時,提供的條件

★表的增刪改查:

1.對數據進行增長數據:

# -*- coding:utf-8 -*-

# file:views.py

from django.shortcuts import render, HttpResponse

# Create your views here.

def home(request):

    from app01 import models

    models.UserInfo.objects.create(username='haha', password='123', age=20)

    return HttpResponse('Home, 建立數據完成.')

1.1也能夠直接傳入字典建立:

def home(request):

    from app01 import models

    dic = {

       'username':'tom',

       'password':'123',

       'age':18,

    }

    models.UserInfo.objects.create(**dic)

    return HttpResponse('Home, 建立數據成功.')

2.刪除數據:

def home(request):

    from app01 import models

    models.UserInfo.objects.filter(username='tom').delete()

3.修改數據:

def home(request):

    from app01 import models

    models.UserInfo.objects.filter(age=20).update(age=22)

    models.UserInfo.objects.all().update(age=22)   # 修改所有數據

4.查詢數據:

def home(request):

    from app01 import models

    list = models.UserInfo.objects.all()  # 獲取所有數據

    models.UserInfo.objects.filter(username='tom').first()   # 獲取第一條數據

    獲取的數據是個列表,querySet類型。

    for item ini list:       # 遍歷列表

       print(item.username)

★使用雙下劃線鏈接操做:

1.獲取個數:

models.Tb1.objects.filter(name='seven').count()

2.比較大小:

models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值

models.Tb1.objects.filter(id__gte=1)             # 獲取id大於等於1的值

models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值

models.Tb1.objects.filter(id__lte=10)            # 獲取id小於10的值

models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 小於10的值

3.是否包含:

models.Tb1.objects.filter(id__in=[11, 22, 33])

models.Tb1.objects.exclude(id__in=[11, 22, 33])  # 至關於not in

4.是否爲空:

Entry.objects.filter(pub_date__isnull=True)

5. contains:

models.Tb1.objects.filter(name__contains="ven")

models.Tb1.objects.filter(name__icontains="ven")#icontains大小寫不敏感

models.Tb1.objects.exclude(name__icontains="ven")

6. range範圍:

models.Tb1.objects.filter(id__range=[1, 2]) # 至關於SQL中的between and

7.其餘的操做:

startswithistartswith, endswith, iendswith,

8. order by:

models.Tb1.objects.filter(name='seven').order_by('id')    # asc

models.Tb1.objects.filter(name='seven').order_by('-id')   # desc

9. group by:

from django.db.models import Count, Min, Max, Sum

models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))

# 至關於:SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

10. limit 、offset:

models.Tb1.objects.all()[10:20]

11. regex正則匹配,iregex 不區分大小寫:

Entry.objects.get(title__regex=r'^(An?|The) +')

Entry.objects.get(title__iregex=r'^(an?|the) +')

12.日期:

Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))

Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

13.年月日周時分秒:

Entry.objects.filter(pub_date__year=2005)

Entry.objects.filter(pub_date__year__gte=2005)

 

Entry.objects.filter(pub_date__month=12)

Entry.objects.filter(pub_date__month__gte=6)

 

Entry.objects.filter(pub_date__day=3)

Entry.objects.filter(pub_date__day__gte=3)

 

Entry.objects.filter(pub_date__week_day=2)

Entry.objects.filter(pub_date__week_day__gte=2)

 

Entry.objects.filter(timestamp__hour=23)

Entry.objects.filter(time__hour=5)

Entry.objects.filter(timestamp__hour__gte=12)

 

Entry.objects.filter(timestamp__minute=29)

Entry.objects.filter(time__minute=46)

Entry.objects.filter(timestamp__minute__gte=29)

 

Entry.objects.filter(timestamp__second=31)

Entry.objects.filter(time__second=2)

Entry.objects.filter(timestamp__second__gte=31)

 

14.extra:

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None),有些狀況下,Django的查詢語法難以簡單的表達複雜的 WHERE 子句,對於這種狀況, Django 提供了 extra() QuerySet 修改機制,它能在 QuerySet生成的SQL從句中注入新子句。不管什麼時候你都須要很是當心的使用extra(). 每次使用它時,您都應該轉義用戶可使用params控制的任何參數,以防止SQL注入***。因爲產品差別的緣由,這些自定義的查詢難以保障在不一樣的數據庫之間兼容(由於你手寫 SQL 代碼的緣由),並且違背了 DRY 原則,因此如非必要,仍是儘可能避免寫 extra。

Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))

Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])

Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

★F和Q:

from django.db.models import F

models.Tb1.objects.update(num=F('num')+1)  #F用於拿到原始數據

# ##方式一:

from django.db.models import Q

con = Q()

 

q1 = Q()

q2 = Q()

 

q1.connecter = 'OR'

 

q1.children.append(('id', 1))

q1.children.append(('id', 2))

q1.children.append(('id', 3))

 

q2.children.append(('c1', 10))

q2.children.append(('c1', 23))

q2.children.append(('c1', 12))

 

con.add('q1', 'AND')

con.add('q1', 'AND')

 

models.Tb.objects.filter(con)

# ##方式二:

Q(nid__gt=10)

Q(nid=8) | Q(nid__gt=10)

Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')

★執行原生SQL:

from django.db import connection, connections

cursor = connection.cursor() 

# 實際上是cursor = connections['default'].cursor()

cursor.execute("""SELECT * from auth_user where id = %s""", [1])

row = cursor.fetchone()

★利用雙下劃線和 _set 將表之間的操做鏈接起來:

1.建立表結構:

from django.db import models

 

# Create your models here.

class UserProfile(models.Model):

    user_info = models.OneToOneField('UserInfo')

    username = models.CharField(max_length=64)

password = models.CharField(max_length=64)

 

    def __unicode__(self):

        return self.username

 

class UserInfo(models.Model):

    user_type_choice = (

        (0, u'普通用戶'),

        (1, u'高級用戶'),

    )

    user_type = models.IntegerField(choices=user_type_choice)

    name = models.CharField(max_length=32)

    email = models.CharField(max_length=32)

    address = models.CharField(max_length=128)

 

    def __unicode__(self):

        return self.name

 

class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField('UserInfo')

    def __unicode__(self):

        return self.caption

 

class Host(models.Model):

    hostname = models.CharField(max_length=64)

    ip = models.GenericIPAddressField()

    user_group = models.ForeignKey('UserGroup')

 

    def __unicode__(self):

        return self.hostname

2.一對一操做:

user_info_obj = models.UserInfo.objects.filter(id=1).first()

print user_info_obj.user_type

print user_info_obj.get_user_type_display()

print user_info_obj.userprofile.password

 

user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()

print user_info_obj.keys()

print user_info_obj.values()

3.一對多操做:

dic = {

    "hostname": "名字1",

    "ip": "192.168.1.1",

    "user_group_id": 1,   # 加對象則爲"user_group"

}

models.Host.objects.create(**dic)

 

# 正向查找一對多

host_obj = models.Host.objects.all()

print(type(host_obj),host_obj)          

# <class 'django.db.models.query.QuerySet'>

# <QuerySet [<Host: 名字1>]>

for item in host_obj:

    print(item.hostname)

    print(item.user_group.caption)

    print(item.user_group.user_info.values())

# <QuerySet [{'name': 'nick', 'user_type': 1, 'id': 1, 'email': '630571017@qq.com', 'address': '128'}]>

usergroup_obj = models.Host.objects.filter(user_group__caption='標題1')

print(usergroup_obj)

 

# 反向查找一對多

usergroup_obj = models.UserGroup.objects.get(id=1)

print(usergroup_obj.caption)

ret = usergroup_obj.host_set.all()  # 全部關於id=1host

print(ret)

obj = models.UserGroup.objects.filter(host__ip='192.168.1.1').values('host__id', 'host__hostname')

print(obj)     

# <QuerySet [{'host__id': 1, 'host__hostname': '名字1'}]>

4.多對多操做:

user_info_obj = models.UserInfo.objects.get(name='nick')

user_info_objs = models.UserInfo.objects.all()

 

group_obj = models.UserGroup.objects.get(caption='CTO')

group_objs = models.UserGroup.objects.all()

 

# 添加數據

#group_obj.user_info.add(user_info_obj)

#group_obj.user_info.add(*user_info_objs)

 

# 刪除數據

#group_obj.user_info.remove(user_info_obj)

#group_obj.user_info.remove(*user_info_objs)

 

# 添加數據

#user_info_obj.usergroup_set.add(group_obj)

#user_info_obj.usergroup_set.add(*group_objs)

 

# 刪除數據

#user_info_obj.usergroup_set.remove(group_obj)

#user_info_obj.usergroup_set.remove(*group_objs)

 

# 獲取數據

#print group_obj.user_info.all()

#print group_obj.user_info.all().filter(id=1)

 

# 獲取數據

#print user_info_obj.usergroup_set.all()

#print user_info_obj.usergroup_set.all().filter(caption='CTO')

#print user_info_obj.usergroup_set.all().filter(caption='DBA')

 

# 添加多對多

# userinfo_id_1 = models.UserInfo.objects.filter(id=1)

# usergroup_id_1 = models.UserGroup.objects.filter(id=1).first()

# usergroup_id_1.user_info.add(*userinfo_id_1)

(5)Django路由系統:

Django的路由系統本質就是URL正則與調用的視圖函數之間的映射表,URL的加載是從配置中開始的。

這樣Django也就很好的支持了靜態路由,基於正則的動態路由,以及二級路由,一樣開發人員也能夠自行使用基於請求方法的路由。

urlpatterns = [

    url(正則表達式, view函數, 參數, 別名),

    Some...

]

參數是可選的要傳遞給視圖函數的默認參數(字典形式)

別名也是可選的

例如:

urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^one',views.one2one),

    url(r'^two',views.one2many),

    url(r'^three',views.many2many),

]

其餘使用正則的例子:

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),

]

說明:

1.要捕獲從URL中的值,用括號括起來,會當參數傳入 views 視圖。

2.沒有必要添加一個斜線,由於每一個URL都有。例如,它^articles不是^/articles。

3.在'r'前面的每一個正則表達式字符串中是可選的,但建議。它告訴Python字符串是「原始」 -沒有什麼字符串中應該進行轉義。

使用正則分組:

urlpatterns = [

    url(r’^index\d{2}/$’,views.index),

url(r’^index2/(?P<id>\d{3})/$’,views.index2),

url(r’^index3/(?P<id>\d{3})/(?P<name>\w+)’,views.index3),

]

def index(request):

    return HttpResponse(‘OK’)

def index2(request, id):

    print(「id=」+str(id))

    return HttpResponse(‘OK’)

def index3(request, id, name):

    print(「id=」+str(id))

    print(「name=」+str(name))

    return HttpResponse(‘OK’)

Django的二級路由示例:

extra_patterns = [

    url(r'^reports/$', credit_views.report),

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

    url(r'^charge/$', credit_views.charge),

]

from django.conf.urls import include, url

urlpatterns = [

    url(r'^$', main_views.homepage),

    url(r'^help/', include('apps.help.urls')), # 這裏是個文件

    url(r'^credit/', include(extra_patterns)),

]

URLconfs 有一個鉤子可讓你加入一些額外的參數到view函數中:

from django.conf.urls import url

from . import views

urlpatterns = [

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

]

須要注意的是,當你加上參數時,對應函數views.year_archive必須加上一個參數,參數名也必須命名爲 foo,這樣就實現了參數名的靜態綁定,放置參數順序出錯。

(6)Django的View視圖函數:

HTTP中產生的兩大對象:

HTTP請求:HttpRequest

HTTP應答:HttpResponse

☆HttpRequest對象:

當請求一個HTML頁面的時候,Django將會建立一個HttpRequest對象包含原數據的請求,而後Django加載適合的視圖,經過HTTPRequest做爲視圖函數的一地個參數。每一個視圖負責返回一個HttpResponse響應。

HttpRequest對象的屬性:

1.path:請求頁面的全路徑,不包括域名

2.method:請求中使用的HTTP方法的字符串表示。全大寫表示。例如

if  req.method=="GET":

Some...

elseif req.method=="POST":

Some...

 

GET:包含全部HTTP GET參數的類字典對象

POST:包含全部HTTP POST參數的類字典對象

服務器收到空的POST請求的狀況也是可能發生的,也就是說,表單form經過HTTP POST方法提交請求,可是表單中可能沒有數據,所以不能使用if req.POST來判斷是否使用了HTTP POST 方法;應該使用if req.method=="POST"

3.COOKIES:包含全部cookies的標準Python字典對象;keysvalues都是字符串。

4.FILES:包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />標籤中 name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys

filename:上傳文件名,用字符串表示

content_type:上傳文件的Content Type

content:上傳文件的原始內容

5.user:是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。能夠經過useris_authenticated()方法來辨別用戶是否登錄:

if req.user.is_authenticated()

只有激活Django中的AuthenticationMiddleware時該屬性纔可用。

6.session:惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Djangosession支持時該屬性纔可用。

7.META:一個標準的Python字典包含全部可用的HTTP頭。可用標題取決於客戶端和服務器,一些例子:

CONTENT_LENGTH         – 請求體的長度(一個字符串)。

CONTENT_TYPE           – 請求體的類型。

HTTP_ACCEPT            - 爲響應能夠接受的內容類型。

HTTP_ACCEPT_ENCODING – 接受編碼的響應

HTTP_ACCEPT_LANGUAGE – 接受語言的反應

HTTP_HOST              – 客戶端發送的HTTP主機頭。

HTTP_REFERER           – 參考頁面

HTTP_USER_AGENT       – 客戶端的用戶代理字符串。

QUERY_STRING          – 查詢字符串,做爲一個單一的(分析的)字符串。

REMOTE_ADDR           – 客戶端的IP地址

REMOTE_HOST           – 客戶端的主機名

REMOTE_USER           – 用戶經過Web服務器的身份驗證。

REQUEST_METHOD       – 字符串,如"GET""POST"

SERVER_NAME           – 服務器的主機名

SERVER_PORT           – 服務器的端口(一個字符串)。

 

☆HttpResponse對象屬性:

對於HtppResponse對象來講,是由Django自動建立的牡丹石HTTPResponse對象必須開發人員手動建立,每一個View請求處理方法必須返回一個HTTPResponse對象。

HTTPResponse對象經常使用的方法:

1.頁面渲染,render,render_to_response,推薦使用render,由於render功能更爲強大。

2.頁面跳轉,redirect

3.頁面傳參,locals,能夠直接將對應視圖中的全部變量所有傳遞給模板。

示例代碼:

def HandlerName(request):

    Some...

    var0, var1 = 1, 2

    Some...

    return render_to_response(‘Home.html’, locals())

對於render的:

render(request, template_name, context=None, content_type=None, status=None, using=None)

結合給定的模板與一個給定的上下文,返回一個字典HttpResponse在渲染文本對象。

request和template_name是必須參數,request指的是傳來的resquest,template_name指的是HTML模板或模板序列的名稱,若是給定的是序列,那麼序列中的第一個模板將被引用。

context         一組字典的值添加到模板中。默認狀況下,這是一個空的字典。

content_type    MIME類型用於生成文檔。

status          爲響應狀態代碼。默認值爲200

using           這個名字一個模板引擎的使用將模板。

(7)Django模板和模板語言:

要使用模板,必然會牽扯到靜態文件的配置,好比CSS,Js等,在Django的項目目錄中的settings.py中追加:

STATICFILES_DIRS = (

        os.path.join(BASE_DIR,'static'),

    )

其中static是存放靜態文件的目錄,這樣就能在HTML頁面中引用特效或者圖片了。對於模板,其實就是讀取模板,模板中嵌套着標籤,而後渲染數據的時候,從Model中取出數據插入到模板中,最後用戶接收到請求的響應。

模板語言:

{{ item }}

{% for item in list %}  <a>{{ item }}</a>  {% endfor %}

{% if ordered_warranty %}  {% else %} {% endif %}

父模板:{% block title %}{% endblock %}

子模板:{% extends "base.html" %}{% block title %}{% endblock %}

其餘經常使用方法:

{{ item.event_start|date:"Y-m-d H:i:s"}}

{{ bio|truncatewords:"30" }}

{{ my_list|first|upper }}

{{ name|lower }}

在字典中取出數據使用dict.some的形式

自定義標籤:

由於在模板語言中不能進行邏輯運算,因此在Django中提供兩種自定義的標籤,一種是simple_tag,另外一種是filter

simple_tag能夠傳遞任意參數,可是不能用做布爾判斷,filter最多隻能傳遞2個參數,能夠用作布爾判斷,一樣的,simple_tag和filter的實現是相似的。

示例代碼:

#!/usr/bin/env python

# -*- conding:utf-8 -*-

# file:mycustomtags.py

from django import template

from django.utils.safestring import mark_safe

from django.template.base import resolve_variable, Node, TemplateSyntaxError

 

register = template.Library()

@register.simple_tag

def my_simple_time(v1,v2,v3):

    return  v1 + v2 + v3

@register.simple_tag

def my_input(id,arg):

    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)

    return mark_safe(result)

在HTML文件中導入以前建立的Python文件,使用load命令:

{% load mycustomtags %}

使用simple_tag:

{% my_simple_time 1 2 3%}

{% my_input 'id_username' 'hide'%}

須要在項目目錄中的settings.py中配置當前的APP:

INSTALLED_APPS = (

    'app0',  # app的名稱

)

(8)Django的中間件:

中間件示意圖:

blob.png

每一次用戶的請求都會一層一層穿過中間件,當不符合中間件的業務邏輯的時候就會直接返回,用戶請求到達不了最裏層的業務邏輯處理函數,這樣能夠自定義中間件,在不使用Nginx等第三方工具的時候統計每次用戶的訪問次數。

中間件其實就是一個Python文件,可是其中的類須要繼承自from django.utils.deprecation import MiddlewareMixin,在這個文件中能夠建立以下5中函數:

# 請求到來以前執行

def process_request(self, request):

Some...

 

# 數據返回以前執行

def process_reponse(self, request, response):

Some...

return response  # 必須返回請求的數據

 

# 執行view中的方法以前執行

def process_view(self, request, callback, callback_args, callback_kwargs)

 

# 程序出錯時執行

def process_exception(self, request, exception)

 

# 渲染模板數據時執行

def process_template_response(self, request, response)

須要在項目目錄中的settings.py文件中設置:

MIDDLEWARE = [

    'middle.first.First',

    'django.middleware.security.SecurityMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',

    'django.middleware.common.CommonMiddleware',

    'django.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.auth.middleware.AuthenticationMiddleware',

    'django.contrib.messages.middleware.MessageMiddleware',

    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

(8)Django文件上傳和Form驗證:

☆自定義文件上傳:

def uploadFile(request):

    if request.method == 'POST':

       obj = request.FILES.get('xxx')

       print(obj.name) # 文件名稱

       f = open(obj,name, 'wb')

       for c in obj.chunks():

           f.write(c)

       f.close()

☆Form上傳:

def upload_file(request):

    if request.method == "POST":

        obj = request.FILES.get('uploadfile')

        f = open(obj.name, 'wb')

        for chunk in obj.chunks():

            f.write(chunk)

        f.close()

    return render(request, 'OK.html')

示例代碼:

# HTML

<form method="post" action="/view1/" enctype="multipart/form-data">

     <input type="file" name="ExcelFile" id="id_ExcelFile" />

     <input type="submit" value="提交" />

</form>

 

# Form

from django import forms

class FileForm(forms.Form):

    ExcelFile = forms.FileField()

 

# Models

from django.db import models

class UploadFile(models.Model):

    userid = models.CharField(max_length = 30)

    file = models.FileField(upload_to = './upload/')

    date = models.DateTimeField(auto_now_add=True)

 

# Views

def UploadFile(request):

    uf = AssetForm.FileForm(request.POST,request.FILES)

    if uf.is_valid():

            upload = models.UploadFile()

            upload.userid = 1

            upload.file = uf.cleaned_data['ExcelFile']

            upload.save()

☆Ajax上傳文件:

# HTML:

<div>

       {{ up.ExcelFile }}

       <input type="button" id="submitj" value="提交" />

</div>

<script src="/static/js/jquery-2.1.4.min.js"></script>

<script>

    $('#submitj').bind("click",function () {

        var file = $('#id_ExcelFile')[0].files[0];

        var form = new FormData();

        form.append('ExcelFile', file);

         $.ajax({

                type:'POST',

                url: '/view1/',

                data: form,

                processData: false,  // tell jQuery not to process the data

                contentType: false,  // tell jQuery not to set contentType

                success: function(arg){

                    console.log(arg);

                }

            })

    })

</script>

# Form:

lass FileForm(forms.Form):

    ExcelFile = forms.FileField()

# Models:

from django.db import models

 

class UploadFile(models.Model):

    userid = models.CharField(max_length = 30)

    file = models.FileField(upload_to = './upload/')

    date = models.DateTimeField(auto_now_add=True)

# Views:

from study1 import forms

 

def UploadFile(request):

    uf = AssetForm.FileForm(request.POST,request.FILES)

    if uf.is_valid():

            upload = models.UploadFile()

            upload.userid = 1

            upload.file = uf.cleaned_data['ExcelFile']

            upload.save()

            print upload.file

return render(request, 'file.html', locals())

(9)Django的Auth認證系統:

auth模塊是Django提供的標準權限管理系統,能夠提供用戶的身份認證,用戶組管理,而且和admin模塊配合使用。

啓用auth模塊:

# Application definition

INSTALLED_APPS = [

    'django.contrib.auth',

]

# model:

from django.contrib.auth.models import User

 

# 數據庫中該表名爲auth_user.

CREATE TABLE "auth_user" (

    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,

    "password" varchar(128) NOT NULL, "last_login" datetime NULL,

    "is_superuser" bool NOT NULL,

    "first_name" varchar(30) NOT NULL,

    "last_name" varchar(30) NOT NULL,

    "email" varchar(254) NOT NULL,

    "is_staff" bool NOT NULL,

    "is_active" bool NOT NULL,

    "date_joined" datetime NOT NULL,

    "username" varchar(30) NOT NULL UNIQUE

)

新建用戶:

user = User.objects.create_user(username, email, password)

user.save()

# 不存儲用戶密碼明文而是存儲一個Hash

認證用戶:

from django.contrib.auth import authenticate

user = authenticate(username=username, password=password)

# 認證用戶的密碼是否有效, 如有效則返回表明該用戶的user對象, 若無效則返回None.

# 該方法不檢查is_active標識位

修改密碼:

user.set_password(new_password)

# 如下實例爲先認證經過後才能夠修改密碼

user = auth.authenticate(username=username, password=old_password)

if user is not None:

    user.set_password(new_password)

    user.save()

登陸:

from django.contrib.auth import login

# loginsession中添加SESSION_KEY, 便於對用戶進行跟蹤:

'login(request, user)'

# login不進行認證,也不檢查is_active標誌位

# 實例:

user = authenticate(username=username, password=password)

if user is not None:

    if user.is_active:

        login(request, user)

退出登陸:

# logout會移除request中的user信息, 並刷新session

from django.contrib.auth import logout

def logout_view(request):

    logout(request)

設置只容許登陸的用戶訪問:

@login_required裝飾器的view函數會先經過session key檢查登陸信息,已經登陸的用戶容許正常執行操做,未登陸的用戶會重定向到login_url指定的位置,這個參數在項目目錄中的settings.py中進行設置。

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')

def userinfo(request):

    Some...

# settings 配置

LOGIN_URL = '/index/'

# views

@login_required

def userinfo(request):

    Some...

(11)跨站請求僞造CSRF:

Django爲了用戶實現放置跨站請求僞造,經過中間件django.middleware.csrf.CsrfViewMiddleware來完成。而對於Django中設置防跨站請求僞造功能分爲全局設置和局部設置。

全局使用就是直接使用django.middleware.csrf.CsrfViewMiddleware,在項目目錄中的settings.py中進行配置。使用裝飾器能夠進行局部的設置:

@csrf_exempt取消當前函數的防跨站請求僞造功能

@csrf_protect僅啓用當前函數的防跨站請求僞造功能

使用時要進行導入:

from django.views.decorators.csrf import csrf_exempt,csrf_protect

在Django1.10中,爲了防止BREACH***,對cookie-form類型的csrf作了一點改進,即在cookie和form中的token值是不相同的。

應用方式也分爲兩種:

☆普通表單使用CSRF:

1.HTML文件中設置令牌:{% csrf_token %}

2.在View函數中設置返回值:return render(request, 'xxx.html', data)

☆Ajax使用CSRF:

對於傳統的form,能夠經過表單的方式將token再次發送到服務端,而對於ajax的話,使用以下方式:

<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

    {% csrf_token %}

 

    <input type="button" onclick="Do();"  value="Do it"/>

 

    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>

    <script src="/static/plugin/jquery/jquery.cookie.js"></script>

    <script type="text/javascript">

        var csrftoken = $.cookie('csrftoken');

 

        function csrfSafeMethod(method) {

            // these HTTP methods do not require CSRF protection

            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));

        }

        $.ajaxSetup({

            beforeSend: function(xhr, settings) {

                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {

                    xhr.setRequestHeader("X-CSRFToken", csrftoken);

                }

            }

        });

        function Do(){

 

            $.ajax({

                url:"/app01/test/",

                data:{id:1},

                type:'POST',

                success:function(data){

                    console.log(data);

                }

            });

 

        }

    </script>

</body>

</html>

(12)Django中的Cookie和Session:

☆獲取cookie:

request.COOKIES['key']

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

    參數:

        default: 默認值

           salt: 加密鹽

        max_age: 後臺控制過時時間

☆設置cookie:

rep = HttpResponse(...) rep render(request, ...)

rep.set_cookie(key,value,...)

rep.set_signed_cookie(key,value,salt='加密鹽',...)

參數:

key,

alue='',

max_age=None,超時時間

expires=None,超時時間(IE requires expires, so set it if hasn't been already.)

path='/', Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie能夠被任何url的頁面訪問

domain=None, Cookie生效的域名

secure=False, https傳輸

httponly=False,只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)

☆使用jQuery操做cookie:

<script src='/static/js/jquery.cookie.js'></script>

$.cookie("list_pager_num", 30,{ path: '/' });

☆Session類型:

Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。

★數據庫:

配置 settings.py:

SESSION_ENGINE = 'django.contrib.sessions.backends.db'  

# 引擎(默認)

SESSION_COOKIE_NAME "sessionid"                      

# Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)

SESSION_COOKIE_PATH "/"                              

# Session的cookie保存的路徑(默認)

SESSION_COOKIE_DOMAIN = None                            

# Session的cookie保存的域名(默認)

SESSION_COOKIE_SECURE = False                            

# 是否Https傳輸cookie(默認)

SESSION_COOKIE_HTTPONLY = True                          

# 是否Session的cookie只支持http傳輸(默認)

SESSION_COOKIE_AGE = 1209600                            

# Session的cookie失效日期(2周)(默認)

SESSION_EXPIRE_AT_BROWSER_CLOSE = False                 

# 是否關閉瀏覽器使得Session過時(默認)

SESSION_SAVE_EVERY_REQUEST = False                      

# 是否每次請求都保存Session,默認修改以後才保存(默認)

def index(request):

    # 獲取、設置、刪除Session中數據

    request.session['k1']

    request.session.get('k1',None)

    request.session['k1'] = 123

    request.session.setdefault('k1',123) # 存在則不設置

    del request.session['k1']

    # 全部 鍵、值、鍵值對

    request.session.keys()

    request.session.values()

    request.session.items()

    request.session.iterkeys()

    request.session.itervalues()

    request.session.iteritems()

 

    # 用戶session的隨機字符串

    request.session.session_key

 

    # 將全部Session失效日期小於當前日期的數據刪除

    request.session.clear_expired()

 

    # 檢查 用戶session的隨機字符串 在數據庫中是否

    request.session.exists("session_key")

 

    # 刪除當前用戶的全部Session數據

    request.session.delete("session_key")

 

    request.session.set_expiry(value)

        * 若是value是個整數,session會在些秒數後失效。

        * 若是value是個datatimetimedeltasession就會在這個時間後失效。

        * 若是value0,用戶關閉瀏覽器session就會失效。

        * 若是valueNone,session會依賴全局session失效策略。

★緩存:

配置 settings.py:

SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 

# 引擎

SESSION_CACHE_ALIAS = 'default'                           

# 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置

SESSION_COOKIE_NAME "sessionid"                       

# Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串

SESSION_COOKIE_PATH "/"                               

# Session的cookie保存的路徑

SESSION_COOKIE_DOMAIN = None                             

# Session的cookie保存的域名

SESSION_COOKIE_SECURE = False                            

# 是否Https傳輸cookie

SESSION_COOKIE_HTTPONLY = True                           

# 是否Session的cookie只支持http傳輸

SESSION_COOKIE_AGE = 1209600                             

# Session的cookie失效日期(2周)

SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  

# 是否關閉瀏覽器使得Session過時

SESSION_SAVE_EVERY_REQUEST = False                       

# 是否每次請求都保存Session,默認修改以後才保存

 

★文件:

配置 settings.py:

SESSION_ENGINE = 'django.contrib.sessions.backends.file'   

# 引擎

SESSION_FILE_PATH = None                                   

# 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T

SESSION_COOKIE_NAME "sessionid"                         

# Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串

SESSION_COOKIE_PATH "/"                                 

# Session的cookie保存的路徑

SESSION_COOKIE_DOMAIN = None                               

# Session的cookie保存的域名

SESSION_COOKIE_SECURE = False                              

# 是否Https傳輸cookie

SESSION_COOKIE_HTTPONLY = True                            

# 是否Session的cookie只支持http傳輸

SESSION_COOKIE_AGE = 1209600                               

# Session的cookie失效日期(2周)

SESSION_EXPIRE_AT_BROWSER_CLOSE = False                    

# 是否關閉瀏覽器使得Session過時

SESSION_SAVE_EVERY_REQUEST = False                         

# 是否每次請求都保存Session,默認修改以後才保存

 

★緩存+數據庫:

數據庫用於作持久化,緩存用於提升效率。

配置 settings.py:

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'       

# 引擎

   

★加密cookieSession:

配置 settings.py:

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'  

# 引擎

(13)Django的緩存:

因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。若是出現多個url匹配同一個view函數的狀況,緩存機制會根據每個不一樣的url作單獨的緩存.Django中提供了6種緩存方式:

☆1.開發調試:

配置:

CACHES = {

       'default': {

'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎

           'TIMEOUT': 300,                                              

# 緩存超時時間(默認300None表示永不過時,0表示當即過時)

           'OPTIONS':{

              'MAX_ENTRIES': 300,                                      

# 最大緩存個數(默認300

              'CULL_FREQUENCY': 3,                                     

# 緩存到達最大個數以後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3

           },

           'KEY_PREFIX': '',                                            

# 緩存key的前綴(默認空)

           'VERSION': 1,                                                 

# 緩存key的版本(默認1

           'KEY_FUNCTION' 函數名                                        

# 生成key的函數(默認函數會生成爲:【前綴:版本:key】)

       }

    }

自定義key:

def default_key_func(key, key_prefix, version):

    """

    Default function to generate keys.

 

    Constructs the key used by all other methods. By default it prepends

    the `key_prefix'. KEY_FUNCTION can be used to specify an alternate

    function with custom key making behavior.

    """

    return '%s:%s:%s' % (key_prefix, version, key)

 

def get_key_func(key_func):

    """

    Function to decide which key function to use.

 

    Defaults to ``default_key_func``.

    """

    if key_func is not None:

       if callable(key_func):

           return key_func

       else:

           return import_string(key_func)

    return default_key_func

☆2.內存:

配置:

CACHES = {

           'default': {

              'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',

              'LOCATION': 'unique-snowflake',

           }

       }

☆3.文件:

配置:

CACHES = {

           'default': {

              'BACKEND': 'django.core.cache.backends.db.DatabaseCache',

              'LOCATION': 'my_cache_table', # 數據庫表

           }

       }

☆4.數據庫:

配置:

CACHES = {

           'default': {

              'BACKEND': 'django.core.cache.backends.db.DatabaseCache',

              'LOCATION': 'my_cache_table', # 數據庫表

           }

       }

執行建立表命令 python manage.py createcachetable

☆5.Memcache緩存(python-memcached模塊):

配置:

CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',

           'LOCATION': '127.0.0.1:11211',

       }

    }

 

    CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',

           'LOCATION': 'unix:/tmp/memcached.sock',

       }

    }  

 

    CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',

           'LOCATION': [

              '172.19.26.240:11211',

              '172.19.26.242:11211',

           ]

       }

    }

☆6.Memcache緩存(pylibmc模塊):

配置:

CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',

           'LOCATION': '127.0.0.1:11211',

       }

    }

 

    CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',

           'LOCATION': '/tmp/memcached.sock',

       }

    }  

 

    CACHES = {

       'default': {

           'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',

           'LOCATION': [

              '172.19.26.240:11211',

              '172.19.26.242:11211',

           ]

       }

    }

☆使用緩存:

1.全站使用緩存:

MIDDLEWARE = [

        'django.middleware.cache.UpdateCacheMiddleware',

        # 其餘中間件...

        'django.middleware.cache.FetchFromCacheMiddleware',

]

2.單獨視圖緩存:

2.1方式一:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)

def my_view(request):

...

 

2.2方式二:

from django.views.decorators.cache import cache_page

urlpatterns = [

    url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),

]

3.局部視圖使用:

引入TemplateTag:{% load cache %}

使用緩存:

{% cache 5000 緩存key %}

     緩存內容

{% endcache %}

(14)Django信號:

Django中提供了「信號調度」,用於在框架執行操做時解耦。通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者。

☆內置信號:

1.Model signals

pre_init                    # djangomodal執行其構造方法前,自動觸發

post_init                   # djangomodal執行其構造方法後,自動觸發

pre_save                    # djangomodal對象保存前,自動觸發

post_save                   # djangomodal對象保存後,自動觸發

pre_delete                  # djangomodal對象刪除前,自動觸發

post_delete                 # djangomodal對象刪除後,自動觸發

m2m_changed # djangomodal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發

class_prepared 程序啓動時,檢測已註冊的appmodal類,對於每個類,自動觸發

 

2.Management signals

pre_migrate                 # 執行migrate命令前,自動觸發

post_migrate                # 執行migrate命令後,自動觸發

 

3.Request/response signals

request_started             # 請求到來前,自動觸發

request_finished            # 請求結束後,自動觸發

got_request_exception      # 請求異常後,自動觸發

 

4.Test signals

setting_changed             # 使用test測試修改配置文件時,自動觸發

template_rendered           # 使用test測試渲染模板時,自動觸發

 

5.Database Wrappers

connection_created          # 建立數據庫鏈接時,自動觸發

使用信號:

from django.core.signals import request_finished

    from django.core.signals import request_started

    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared

    from django.db.models.signals import pre_init, post_init

    from django.db.models.signals import pre_save, post_save

    from django.db.models.signals import pre_delete, post_delete

    from django.db.models.signals import m2m_changed

    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed

    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created

# 定義接收到信號時執行的回調函數

    def callback(sender, **kwargs):

        print("內置信號_callback")

        print(sender,kwargs)

#註冊信號

    內置信號.connect(callback)

或:

    from django.core.signals import request_finished

    from django.dispatch import receiver

 

    @receiver(request_finished)

    def my_callback(sender, **kwargs):

       print("Request finished!")

☆自定義信號:

1.定義信號:

import django.dispatch

pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

2.註冊信號:

def callback(sender, **kwargs):

    print("callback")

    print(sender,kwargs)

 

pizza_done.connect(callback)

3.觸發信號:

from 路徑 import pizza_done

pizza_done.send(sender='seven',toppings=123, size=456)

(16)Django中的Admin:

Django admin是一個Django提供的後臺管理頁面,這個管理頁面提供完善的HTML和CSS,是的在model中建立表結構後,在admin中就能夠增刪改查,配置Django的Admin須要如下步驟:

1.建立後臺管理員

python manage.py createsuperuser

2.配置URL

url(r'^admin/', include(admin.site.urls))

3.註冊和配置Django Admin後臺管理頁面admin.py

admin中的配置:

from django.contrib import admin

# Register your models here.

admin.site.register(models.UserType)

admin.site.register(models.UserInfo)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

設置數據表名稱:

class UserType(models.Model):

    name = models.CharField(max_length=50)

 

    class Meta:

        verbose_name = '用戶類型'

        verbose_name_plural = '用戶類型'

在model中還要:

class UserType(models.Model):

    name = models.CharField(max_length=50)

 

    def __unicode__(self):  # python3 is __str__(self)

        return self.name

爲數據表添加搜索功能:

from django.contrib import admin

 

from app01 import  models

 

class UserInfoAdmin(admin.ModelAdmin):

    list_display = ('username', 'password', 'email')

    search_fields = ('username', 'email')

 

admin.site.register(models.UserType)

admin.site.register(models.UserInfo,UserInfoAdmin)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

添加快速過濾:

from django.contrib import admin

from app01 import  models

 

class UserInfoAdmin(admin.ModelAdmin):

    list_display = ('username', 'password', 'email')

    search_fields = ('username', 'email')

    list_filter = ('username', 'email')

 

admin.site.register(models.UserType)

admin.site.register(models.UserInfo,UserInfoAdmin)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

(17)Django中的Form:

Django中的Form通常用來輸入HTML或者驗證用戶輸入。

# Form:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

 

import re

from django import forms

from django.core.exceptions import ValidationError

 

 

def mobile_validate(value):

    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')

    if not mobile_re.match(value):

        raise ValidationError('手機號碼格式錯誤')

 

 

class PublishForm(forms.Form):

 

    user_type_choice = (

        (0, u'普通用戶'),

        (1, u'高級用戶'),

    )

 

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,

                                                                  attrs={'class': "form-control"}))

 

    title = forms.CharField(max_length=20,

                            min_length=5,

                            error_messages={'required': u'標題不能爲空',

                                            'min_length': u'標題最少爲5個字符',

                                            'max_length': u'標題最多爲20個字符'},

                            widget=forms.TextInput(attrs={'class': "form-control",

                                                          'placeholder': u'標題5-20個字符'}))

 

    memo = forms.CharField(required=False,

                           max_length=256,

                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'詳細描述', 'rows': 3}))

 

    phone = forms.CharField(validators=[mobile_validate, ],

                            error_messages={'required': u'手機不能爲空'},

                            widget=forms.TextInput(attrs={'class': "form-control",

                                                          'placeholder': u'手機號碼'}))

 

    email = forms.EmailField(required=False,

                            error_messages={'required': u'郵箱不能爲空','invalid': u'郵箱格式錯誤'},

                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))

 

# View:

def publish(request):

    ret = {'status': False, 'data': '', 'error': '', 'summary': ''}

    if request.method == 'POST':

        request_form = PublishForm(request.POST)

        if request_form.is_valid():

            request_dict = request_form.clean()

            print request_dict

            ret['status'] = True

        else:

            error_msg = request_form.errors.as_json()

            ret['error'] = json.loads(error_msg)

    return HttpResponse(json.dumps(ret))

在使用Model和Form時,都須要對字段進行定義並指定類型,經過ModelForm則能夠省去Form中字段的定義:

class AdminModelForm(forms.ModelForm):

     

    class Meta:

        model = models.Admin

        #fields = '__all__'

        fields = ('username', 'email')

         

        widgets = {

            'email' : forms.PasswordInput(attrs={'class':"alex"}),

        }

相關文章
相關標籤/搜索