Web框架之Django:
(1)簡介:
Django是一個由Python寫成開源的重量級Web應用框架,采用MTV的框架模式。它最初是被開發來用于管理勞倫斯出版集團旗下的一些以新聞內容為主的網站的,即是CMS(內容管理系統)軟件。并于2005年7月在BSD許可證下發布。這套框架是以比利時的吉普賽爵士吉他手Django Reinhardt來命名的。Django的優勢在于:大而全,框架本身集成了ORM、模型綁定、模板引擎、緩存、Session等諸多功能。
(2)Django的處理流程:
當用戶發出HTTP請求,URLhandler接收用戶請求,根據開發人員設置的路由規則匹配相應的處理類
根據請求的類型判斷調用的HTTP方法
如果需要連接數據庫,Views中的函數將會調用Models的方法,否則直接去Template中取出HTML頁面直接返回
調用Models的時候,Models會去數據庫讀取數據再返回給Views
經過渲染頁面一起將最終的HTML頁面返回給頁面
☆MTV與MVC:
MTV和MVC的思想是一樣的的,只是思想的體現有所不同。
MVC:M管理應用程序的狀態,并約束改變狀態的行為,一般叫做業務規則;V負責把數據格式化后呈現給用戶查看;C接收用戶操作,根據訪問模型獲取數據,并調用視圖顯示這些數據,控制器(處理器)用于將模型與視圖隔離并成為二者之間的聯系紐帶。
MTV:M代表數據存取層,也就是Model,改成處理與數據相關的所有事務如何存取,如何驗證數據的有效性,包含哪些行為與數據相關;T指的是表現層,該層處理與現實相關的行為,如何在頁面文檔中顯示數據,展現內容,也就是Template;V代表業務邏輯層,該層包含存取模型及調取恰當模板的相關邏輯。
☆Django版的MTV:
Django也是一個MVC框架。但是在Django中,控制器接受用戶輸入的部分由框架自行處理,所以 Django 里更關注的是模型(Model)、模板(Template)和視圖(Views),稱為 MTV模式。
☆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>
可視化如下:
其他的字段參數:
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
日期類型,在數據庫中對應datetime,auto_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
字符串類型(ip4和ip6是可選的),參數protocol可以是:both、ipv4、ipv6,驗證時,會根據設置報錯
15.models.NullBooleanField
允許為空的布爾類型
16.models.PositiveIntegerFiel
正數范圍的Integer
17.models.PositiveSmallIntegerField
正數范圍的smallInteger
18.models.SlugField
減號、下劃線、字母、數字
19.models.SmallIntegerField
數字,數據庫中的字段有:tinyint、smallint、int、bigint
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')
Model的clean方法是一個鉤子,可用于定制操作,如:上述的異常處理。
★連表操作:
一對多: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, # 在Admin或ModelForm中顯示關聯數據時,提供的條件
★表的增刪改查:
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)
- contains:
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven")#icontains大小寫不敏感
models.Tb1.objects.exclude(name__icontains="ven")
- range范圍:
models.Tb1.objects.filter(id__range=[1, 2]) # 相當于SQL中的between and
7.其他的操作:
startswith,istartswith, endswith, iendswith,
- order by:
models.Tb1.objects.filter(name='seven').order_by('id') # asc
models.Tb1.objects.filter(name='seven').order_by('-id') # desc
- 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"
- limit 、offset:
models.Tb1.objects.all()[10:20]
- 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=1的host
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字典對象;keys和values都是字符串。
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的實例。可以通過user的is_authenticated()方法來辨別用戶是否登陸:
if req.user.is_authenticated();
只有激活Django中的AuthenticationMiddleware時該屬性才可用。
6.session:唯一可讀寫的屬性,代表當前會話的字典對象;自己有激活Django中session支持時該屬性才可用。
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的中間件:
中間件示意圖:
每一次用戶的請求都會一層一層穿過中間件,當不符合中間件的業務邏輯的時候就會直接返回,用戶請求到達不了最里層的業務邏輯處理函數,這樣可以自定義中間件,在不使用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
login向session中添加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是個datatime或timedelta,session就會在這個時間后失效。
* 如果value是0,用戶關閉瀏覽器session就會失效。
* 如果value是None,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,
緩存超時時間(默認300,None表示永不過期,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 # django的modal執行其構造方法前,自動觸發
post_init # django的modal執行其構造方法后,自動觸發
pre_save # django的modal對象保存前,自動觸發
post_save # django的modal對象保存后,自動觸發
pre_delete # django的modal對象刪除前,自動觸發
post_delete # django的modal對象刪除后,自動觸發
m2m_changed # django的modal中使用m2m字段操作第三張表(add,remove,clear)前后,自動觸發
class_prepared 程序啟動時,檢測已注冊的app中modal類,對于每一個類,自動觸發
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"}),
}