MVC框架的核心思想是:解耦,讓不一樣的代碼塊之間下降耦合,加強代碼的可擴展性和可移植性,實現向後兼容javascript
在ORM框架中,它幫咱們把類和數據表進行了一個映射,可讓咱們經過類和類對象就能操做它所對應的表格中的數據。ORM框架還有一個功能,它能夠根據咱們設計的類自動幫咱們生成數據庫中的表格,省去了咱們本身建表的過程css
說明:不須要定義主鍵列,在生成時會自動添加,而且值爲自動增加html
數據表的默認名稱爲:<app_name>_<model_name>前端
一對多的關係(ForeignKey)應定義在多的那個類中java
登陸後臺管理後,默認沒有咱們建立的應用中定義的模型類,須要在本身應用中的admin.py文件中註冊,才能夠在後臺管理中看到,並進行增刪改查操做python
Django提供了自定義管理頁面的功能,好比列表頁要顯示哪些值mysql
1 from django.contrib import admin 2 from booktest.models import BookInfo,HeroInfo 3 4 class BookInfoAdmin(admin.ModelAdmin): 5 list_display = ['id', 'btitle', 'bpub_date'] 6 class HeroInfoAdmin(admin.ModelAdmin): 7 list_display = ['id', 'hname','hgender','hcomment'] 8 9 admin.site.register(BookInfo,BookInfoAdmin) 10 admin.site.register(HeroInfo,HeroInfoAdmin)
/settings.py文件,找到DATABASES項,默認使用SQLite3數據庫jquery
修改成使用MySQL數據庫,代碼以下: 將引擎改成mysql,提供鏈接的主機HOST、端口PORT、數據庫名NAME、用戶名USER、密碼PASSWORD。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test2', #數據庫名字, 'USER': 'root', #數據庫登陸用戶名 'PASSWORD': 'mysql', #數據庫登陸密碼 'HOST': 'localhost', #數據庫所在主機 'PORT': '3306', #數據庫端口 } }
注意:數據庫test2 Django框架不會自動生成,須要咱們本身進入mysql數據庫去建立git
使用時須要引入django.db.models包,字段類型以下:正則表達式
AutoField:自動增加的IntegerField,一般不用指定,不指定時Django會自動建立屬性名爲id的自動增加屬性。 BooleanField:布爾字段,值爲True或False。 NullBooleanField:支持Null、True、False三種值。 CharField(max_length=字符長度):字符串。 參數max_length表示最大字符個數。 TextField:大文本字段,通常超過4000個字符時使用。 IntegerField:整數。 DecimalField(max_digits=None, decimal_places=None):十進制浮點數。 參數max_digits表示總位數。 參數decimal_places表示小數位數。 FloatField:浮點數。 DateField[auto_now=False, auto_now_add=False]):日期。 參數auto_now表示每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,默認爲false。 參數auto_now_add表示當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false。 參數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤。 TimeField:時間,參數同DateField。 DateTimeField:日期時間,參數同DateField。 FileField:上傳文件字段。 ImageField:繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片。
經過選項實現對字段的約束,選項以下:
null:若是爲True,表示容許爲空,默認值是False。 blank:若是爲True,則該字段容許爲空白,默認值是False。 對比:null是數據庫範疇的概念,blank是表單驗證範疇的。 db_column:字段的名稱,若是未指定,則使用屬性的名稱。 db_index:若值爲True, 則在表中會爲此字段建立索引,默認值是False。 default:默認值。 primary_key:若爲True,則該字段會成爲模型的主鍵字段,默認值是False,通常做爲AutoField的選項使用。 unique:若是爲True, 這個字段在表中必須有惟一值,默認值是False。
1 list=BookInfo.objects.filter(id__exact=1) 2 可簡寫爲: 3 list=BookInfo.objects.filter(id=1)
說明:若是要包含%無需轉義,直接寫便可
list = BookInfo.objects.filter(btitle__contains='傳')
1 list = BookInfo.objects.filter(btitle__endswith='部')
以上運算符都區分大小寫,在這些運算符前加上i表示不區分大小寫,如iexact、icontains、istartswith、iendswith
list = BookInfo.objects.filter(btitle__isnull=False)
1 list = BookInfo.objects.filter(id__in=[1, 3, 5])
list = BookInfo.objects.filter(id__gt=3)
1 list = BookInfo.objects.exclude(id=3)
list = BookInfo.objects.filter(bpub_date__year=1980)
list = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
兩個屬性比較使用F對象
1 list = BookInfo.objects.filter(bread__gte=F('bcomment')) 2 list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
多個過濾器逐個調用表示邏輯與關係,同sql語句中where部分的and關鍵字
1 list=BookInfo.objects.filter(bread__gt=20,id__lt=3) 2 或 3 list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3) 4 5 list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3)) 6 7 Q對象前可使用~操做符,表示非not 8 list = BookInfo.objects.filter(~Q(pk=3))
使用aggregate()過濾器調用聚合函數。聚合函數包括:Avg,Count,Max,Min,Sum,被定義在django.db.models中
list = BookInfo.objects.aggregate(Sum('bread'))
注意aggregate的返回值是一個字典類型,格式以下:
{'聚合類小寫__屬性名':值} 如:{'sum__bread':3}
使用count時通常不使用aggregate()過濾器,count函數的返回值是一個數字
list = BookInfo.objects.count()
all():返回全部數據。 filter():返回知足條件的數據。 exclude():返回知足條件以外的數據,至關於sql語句中where部分的not關鍵字。 order_by():對結果進行排序
get():返回單個知足條件的對象 若是未找到會引起"模型類.DoesNotExist"異常。 若是多條被返回,會引起"模型類.MultipleObjectsReturned"異常。 count():返回當前查詢結果的總條數。 aggregate():聚合,返回一個字典。
exists():判斷查詢集中是否有數據,若是有則返回True,沒有則返回False
惰性執行:建立查詢集不會訪問數據庫,直到調用數據時,纔會訪問數據庫,調用數據的狀況包括迭代、序列化、與if合用。 緩存:使用同一個查詢集,第一次使用時會發生數據庫的查詢,而後把結果緩存下來,再次使用這個查詢集時會使用緩存的數據
每一個查詢集都包含一個緩存來最小化對數據庫的訪問。 在新建的查詢集中,緩存爲空,首次對查詢集求值時,會發生數據庫查詢,django會將查詢的結果存在查詢集的緩存中,並返回請求的結果,接下來對查詢集求值將重用緩存中的結果。
能夠對查詢集進行取下標或切片操做,等同於sql中的limit和offset子句。 注意:不支持負數索引。 對查詢集進行切片後返回一個新的查詢集,不會當即執行查詢。 若是獲取一個對象,直接使用[0],等同於[0:1].get(),可是若是沒有數據,[0]引起IndexError異常,[0:1].get()若是沒有數據引起DoesNotExist異常。 示例:獲取第一、2項,運行查看。 list=BookInfo.objects.all()[0:2]
#定義圖書模型類BookInfo class BookInfo(models.Model): ... #定義元選項 class Meta: db_table='bookinfo' #指定BookInfo生成的數據表名爲bookinfo
1 url(r'^delete(\d+)/$',views.show_arg) 2 def show_arg(request,id): 3 return HttpResponse('show arg %s'%id)
1 url(r'^delete(?P<id1>\d+)/$',views.show_arg) 2 def show_arg(request,id1): 3 return HttpResponse('show %s'%id1)
下面除非特別說明,屬性都是隻讀的
path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分。 method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'。 在瀏覽器中給出地址發出請求採用get方式,如超連接。 在瀏覽器中點擊表單的提交按鈕發起請求,若是表單的method設置爲post則爲post請求。 encoding:一個字符串,表示提交的數據的編碼方式。 若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8。 這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。 GET:QueryDict類型對象,相似於字典,包含get請求方式的全部參數。 POST:QueryDict類型對象,相似於字典,包含post請求方式的全部參數。 FILES:一個相似於字典的對象,包含全部的上傳文件。 COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串。 session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見"狀態保持"。
content:表示返回的內容。 charset:表示response採用的編碼字符集,默認爲utf-8。 status_code:返回的HTTP響應狀態碼。 content-type:指定返回數據的的MIME類型,默認爲'text/html'。
_init_:建立HttpResponse對象後完成返回內容的初始化。 set_cookie:設置Cookie信息。 set_cookie(key, value='', max_age=None, expires=None) cookie是網站以鍵值對格式存儲在瀏覽器中的一段純文本信息,用於實現用戶跟蹤。 max_age是一個整數,表示在指定秒數後過時。 expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過時。 max_age與expires二選一。 若是不指定過時時間,在關閉瀏覽器時cookie會過時。 delete_cookie(key):刪除指定的key的Cookie,若是key不存在則什麼也不發生。 write:向響應體中寫數據。
有時須要保存下來用戶瀏覽的狀態,好比用戶是否登陸過,瀏覽過哪些商品等。 實現狀態保持主要有兩種方式
response.set_cookie('h1', '你好')
response.write('<h1>' + request.COOKIES['h1'] + '</h1>')
在服務器端進行狀態保持的方案就是Session
Django項目默認啓用Session
/settings.py文件,設置SESSION_ENGINE項指定Session數據存儲的方式,能夠存儲在數據庫、緩存、Redis等
SESSION_ENGINE='django.contrib.sessions.backends.db'
SESSION_ENGINE='django.contrib.sessions.backends.cache'
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
全部請求者的Session都會存儲在服務器中,服務器如何區分請求者和Session數據的對應關係呢?
在使用Session後,會在Cookie中存儲一個sessionid的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid後,會根據這個值找出這個請求者的Session
結果:若是想使用Session,瀏覽器必須支持Cookie,不然就沒法使用Session了
存儲Session時,鍵與Cookie中的sessionid相同,值是開發人員設置的鍵值對信息,進行了base64編碼,過時時間由開發人員設置
經過HttpRequest對象的session屬性進行會話的讀寫操做
request.session['鍵']=值
request.session.get('鍵',默認值)
request.session.clear()
request.session.flush()
del request.session['鍵']
設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時
會話還支持文件、純cookie、Memcached、Redis等方式存儲
pip install django-redis-sessions==0.5.6
SESSION_ENGINE = 'redis_sessions.session' SESSION_REDIS_HOST = 'localhost' SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 2 SESSION_REDIS_PASSWORD = '' SESSION_REDIS_PREFIX = 'session'
for標籤語法以下: {%for item in 列表%} 循環邏輯 {{forloop.counter}}表示當前是第幾回循環,從1開始 {%empty%} 列表爲空或不存在時執行此邏輯 {%endfor%} if標籤語法以下: {%if ...%} 邏輯1 {%elif ...%} 邏輯2 {%else%} 邏輯3 {%endif%}
變量|過濾器:參數
data|default:'默認值'
日期date,用於對日期類型的值進行字符串格式化,經常使用的格式化字符以下:
Y表示年,格式爲4位,y表示兩位的年。 m表示月,格式爲01,02,12等。 d表示日, 格式爲01,02等。 j表示日,格式爲1,2等。 H表示時,24進制,h表示12進制的時。 i表示分,爲0-59。 s表示秒,爲0-59。 value|date:"Y年m月j日 H時i分s秒"
過濾器escape能夠實現對變量的html轉義,默認模板就會轉義,通常省略
{{t1|escape}}
過濾器safe:禁用轉義,告訴模板這個變量是安全的,能夠解釋執行
{{data|safe}}
標籤autoescape:設置一段代碼都禁用轉義,接受on、off參數
{%autoescape off%} ... {%endautoescape%}
CSRF全拼爲Cross Site Request Forgery,譯爲跨站請求僞造。CSRF指攻擊者盜用了你的身份,以你的名義發送惡意請求
1 from PIL import Image, ImageDraw, ImageFont 2 from django.utils.six import BytesIO 3 ... 4 def verify_code(request): 5 #引入隨機函數模塊 6 import random 7 #定義變量,用於畫面的背景色、寬、高 8 bgcolor = (random.randrange(20, 100), random.randrange( 9 20, 100), 255) 10 width = 100 11 height = 25 12 #建立畫面對象 13 im = Image.new('RGB', (width, height), bgcolor) 14 #建立畫筆對象 15 draw = ImageDraw.Draw(im) 16 #調用畫筆的point()函數繪製噪點 17 for i in range(0, 100): 18 xy = (random.randrange(0, width), random.randrange(0, height)) 19 fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) 20 draw.point(xy, fill=fill) 21 #定義驗證碼的備選值 22 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' 23 #隨機選取4個值做爲驗證碼 24 rand_str = '' 25 for i in range(0, 4): 26 rand_str += str1[random.randrange(0, len(str1))] 27 #構造字體對象,ubuntu的字體路徑爲「/usr/share/fonts/truetype/freefont」 28 font = ImageFont.truetype('FreeMono.ttf', 23) 29 #構造字體顏色 30 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) 31 #繪製4個字 32 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) 33 draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) 34 draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) 35 draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) 36 #釋放畫筆 37 del draw 38 #存入session,用於作進一步驗證 39 request.session['verifycode'] = rand_str 40 #內存文件操做 41 buf = BytesIO() 42 #將圖片保存在內存中,文件類型爲png 43 im.save(buf, 'png') 44 #將內存中的圖片數據返回給客戶端,MIME類型爲圖片png 45 return HttpResponse(buf.getvalue(), 'image/png')
1 def verify_yz(request): 2 yzm=request.POST.get('yzm') 3 verifycode=request.session['verifycode'] 4 response=HttpResponse('no') 5 if yzm==verifycode: 6 response=HttpResponse('ok') 7 return response
<script type="text/javascript" src="/static/jquery-1.12.4.min.js"></script> <script type="text/javascript"> $(function(){ $('#change').css('cursor','pointer').click(function() { $('#yzm').attr('src',$('#yzm').attr('src')+1) }); }); </script> ... <img id="yzm" src="/verify_code/?1"/> <span id="change">看不清,換一個</span>
在定義url時,須要爲include定義namespace屬性,爲url定義name屬性,使用時,在模板中使用url標籤,在視圖中使用reverse函數,根據正則表達式動態生成地址,減輕後期維護成本
url(r'^',include('booktest.urls',namespace='booktest')) url(r'^fan2/$', views.fan2,name='fan2') 反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a> return redirect(reverse('booktest:fan2'))
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
方法_init_(列表,int):返回分頁對象,第一個參數爲列表數據,第二個參數爲每頁數據的條數。 屬性count:返回對象總數。 屬性num_pages:返回頁面總數。 屬性page_range:返回頁碼列表,從1開始,例如[1, 2, 3, 4]。 方法page(m):返回Page類實例對象,表示第m頁的數據,下標以1開始
調用Paginator對象的page()方法返回Page對象,不須要手動構造。 屬性object_list:返回當前頁對象的列表。 屬性number:返回當前是第幾頁,從1開始。 屬性paginator:當前頁對應的Paginator對象。 方法has_next():若是有下一頁返回True。 方法has_previous():若是有上一頁返回True。 方法len():返回當前頁面對象的個數。
1 from django.core.paginator import Paginator 2 from booktest.models import AreaInfo 3 ... 4 #參數pIndex表示:當前要顯示的頁碼 5 def page_test(request,pIndex): 6 #查詢全部的地區信息 7 list1 = AreaInfo.objects.filter(aParent__isnull=True) 8 #將地區信息按一頁10條進行分頁 9 p = Paginator(list1, 10) 10 #若是當前沒有傳遞頁碼信息,則認爲是第一頁,這樣寫是爲了請求第一頁時能夠不寫頁碼 11 if pIndex == '': 12 pIndex = '1' 13 #經過url匹配的參數都是字符串類型,轉換成int類型 14 pIndex = int(pIndex) 15 #獲取第pIndex頁的數據 16 list2 = p.page(pIndex) 17 #獲取全部的頁碼信息 18 plist = p.page_range 19 #將當前頁碼、當前頁的數據、頁碼信息傳遞到模板中 20 return render(request, 'booktest/page_test.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})
url(r'^page(?P<pIndex>[0-9]*)/$', views.page_test)
<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}} {%else%} <a href="/page{{pindex}}/">{{pindex}}</a> {%endif%} {%endfor%} </body> </html>
1 <html> 2 <head> 3 <title>省市區列表</title> 4 <script type="text/javascript" src="/static/js/jquery-1.12.4.min.js"></script> 5 <script type="text/javascript"> 6 $(function(){ 7 //頁面加載完成後獲取省信息,並添加到省select 8 $.get('/area2/',function(dic) { 9 pro=$('#pro') 10 $.each(dic.data,function(index,item){ 11 pro.append('<option value='+item[0]+'>'+item[1]+'</option>'); 12 }) 13 }); 14 //爲省select綁定change事件,獲取市信息,並添加到市select 15 $('#pro').change(function(){ 16 $.get('/area3_'+$(this).val()+'/',function(dic){ 17 city=$('#city'); 18 city.empty().append('<option value="">請選擇市</option>'); 19 dis=$('#dis'); 20 dis.empty().append('<option value="">請選擇區縣</option>'); 21 $.each(dic.data,function(index,item){ 22 city.append('<option value='+item[0]+'>'+item[1]+'</option>'); 23 }) 24 }); 25 }); 26 //爲市select綁定change事件,獲取區縣信息,並添加到區縣select 27 $('#city').change(function(){ 28 $.get('/area3_'+$(this).val()+'/',function(dic){ 29 dis=$('#dis'); 30 dis.empty().append('<option value="">請選擇區縣</option>'); 31 $.each(dic.data,function(index,item){ 32 dis.append('<option value='+item[0]+'>'+item[1]+'</option>'); 33 }) 34 }) 35 }); 36 37 }); 38 </script> 39 </head> 40 <body> 41 <select id="pro"> 42 <option value="">請選擇省</option> 43 </select> 44 <select id="city"> 45 <option value="">請選擇市</option> 46 </select> 47 <select id="dis"> 48 <option value="">請選擇區縣</option> 49 </select> 50 </body> 51 </html
情景:用戶發起request,並等待response返回。在本些views中,可能須要執行一段耗時的程序,那麼用戶就會等待很長時間,形成很差的用戶體驗,好比發送郵件、手機驗證碼等
INSTALLED_APPS = ( ... 'djcelery', }
import djcelery djcelery.setup_loader() BROKER_URL = 'redis://127.0.0.1:6379/2'
1 import time 2 from celery import task 3 4 @task 5 def sayhello(): 6 print('hello ...') 7 time.sleep(2) 8 print('world ...')
1 from booktest import tasks 2 ... 3 def sayhello(request): 4 # print('hello ...') 5 # time.sleep(2) 6 # print('world ...') 7 tasks.sayhello.delay() 8 return HttpResponse("hello world")
python manage.py migrate
sudo service redis start
python manage.py celery worker --loglevel=info
1 from django.conf import settings 2 from django.core.mail import send_mail 3 from celery import task 4 5 @task 6 def sayhello(): 7 msg='<a href="http://www.itcast.cn/subject/pythonzly/index.shtml" target="_blank">點擊激活</a>' 8 send_mail('註冊激活','',settings.EMAIL_FROM, 9 ['itcast88@163.com'], 10 html_message=msg)
請使用手機"掃一掃"x