M全拼爲Model,主要封裝對數據庫層的訪問,對數據庫中的數據進行增、刪、改、查操做javascript
V全拼爲View,用於封裝結果,生成頁面展現的html內容css
C全拼爲Controller,用於接收請求,處理業務邏輯,與Model和View交互,返回結果html
M全拼爲Model,與MVC中的M功能相同,負責和數據庫交互,進行數據處理java
V全拼爲View,與MVC中的C功能相同,接收請求,進行業務處理,返回應答python
T全拼爲Template,與MVC中的V功能相同,負責封裝構造要返回的htmlmysql
爲何要使用虛擬環境?jquery
若是在一臺機器上,想開發不一樣的項目,這些項目依賴的同一個包的版本不一樣,其餘項目就沒法正常運行了,全部咱們要用到虛擬環境,虛擬環境就是對真實Python環境的複製,經過創建多個虛擬環境,在不一樣的虛擬環境中開發項目就實現了項目之間的間隔git
建立虛擬環境正則表達式
pip3 install virtualenv # 安裝虛擬環境 pip3 install virtualenvwrapper-win # 安裝虛擬環境擴展包 mkvirtualenv 虛擬環境名稱 # 建立虛擬環境 deactivate # 退出虛擬環境 workon # 直接輸入workon查看已建立的虛擬環境,後面接虛擬環境名稱進入該虛擬環境 rmvirtualenv 虛擬環境名稱 # 刪除虛擬環境 pip list # 查看該虛擬環境中安裝的包 pip install # 虛擬環境包管理 pip install django==1.11.11 # 安裝django1.11.11
建立第一個項目sql
django-admin startproject mysite;
項目默認目錄
manage.py # 項目管理文件,經過它管理項目 與項目同名的目錄,此處爲mysite _init_.py # 一個空文件,做用是這個目錄test能夠被看成包使用 settings.py # 項目的總體配置文件 urls.py # 項目的URL配置文件 wsgi.py # 項目與WSGI兼容的Web服務器入口
建立應用
python manage.py startapp app01;
應用目錄結構
__init__.py # 一個空文件,表示當前目錄能夠看成一個python包使用 tests.py # 開發測試用例,在實際開發中會有專門的測試人員 models.py # 數據庫操做相關 views.py # 接收瀏覽器請求,進行處理,返回頁面相關 admin.py # 站點管理 migrations:
安裝應用
# mysite/setting.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
開發服務器
python manage.py runserver ip:端口
定義模型類
# app01/models.py from django.db import models class BookInfo(models.Model): """圖書表""" btitle = models.CharField(max_length=20) bpub_date = models.DateField() class HeroInfo(models.Model): """英雄表""" hname = models.CharField(max_length=20) hgender = models.BooleanField() hcomment = models.CharField(max_length=100) hbook = models.ForeignKey(BookInfo)
遷移
python manage makemigration # 生成遷移文件 python manage migrate # 執行遷移
數據操做
# 進入項目並引入模塊 python manage.py shell from datetime import date from booktest.models import BookInfo,HeroInfo # 增刪改查 BookInfo.objects.create(title="射鵰英雄傳",bpub_date=date(2018,10,4)) BookInfo.objects.filter(id=1).delete() BookInfo.objects.filter(id=1).update(title='神鵰俠侶') BookInfo.objects.filter.all() # 對象關聯操做 HeroInfo.objects.create(hname='a1',hgender=False,hcomment='he is a boy',hbook=BookInfo.objects.get(id=1)) # 得到關聯集合 BookInfo.objects.get(id=1).heroinfo_set.all()
管理頁面本地化
# mysite/setting.py LANGUAGE_CODE = 'zh-hans' #使用中國語言 TIME_ZONE = 'Asia/Shanghai' #使用中國上海時間
建立管理員
python manage.py createsuperuser
註冊模型類
# app01/admin.py from django.contrib import admin from app01.models import BookInfo,HeroInfo admin.site.register(BookInfo) admin.site.register(HeroInfo)
自定義管理界面
# app01/admin.py,list_display表示要顯示的字段 from django.contrib import admin from booktest.models import BookInfo,HeroInfo class BookInfoAdmin(admin.ModelAdmin): list_display = ['id', 'btitle', 'bpub_date'] class HeroInfoAdmin(admin.ModelAdmin): list_display = ['id', 'hname','hgender','hcomment'] admin.site.register(BookInfo,BookInfoAdmin) admin.site.register(HeroInfo,HeroInfoAdmin)
定義視圖
# app01/views.py from django.http import HttpResponse def index(request): return HttpResponse("index")
配置URLconf
請求者在瀏覽器中輸入url,請求到網站後,獲取url信息,而後在URL.conf逐條匹配,若是匹配成功返回相應的視圖函數,若是全部URLconf都沒有匹配成功,返回404錯誤 # app01/views.py from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^', include('app01.urls')), ] # mysite/urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^$', views.index), ]
建立模板
# mysite/setting.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
定義模板
# templtes/app01/index.html <html> <head> <title>圖書列表</title> </head> <body> <h1>{{title}}</h1> {%for i in list%} {{i}}<br> {%endfor%} </body> </html>
視圖調用模板
# app01/views.py from django.shortcuts import render def index(request): context={'title':'圖書列表','list':range(10)} return render(request,'app01/index.html',context)
負責和數據庫交互,進行數據處理
什麼是orm?
對象關係映射,是隨着面向對象思想發展而產生的,是一種程序技術,用於實現面向對象編程語言裏不一樣類型系統的數據之間的轉換,面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關係數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別,爲了解決這個不匹配的現象,對象關係映射技術應運而生
使用MySQL
# mysite/setting.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'python', #數據庫名字, 'USER': 'root', #數據庫登陸用戶名 'PASSWORD': '123456', #數據庫登陸密碼 'HOST': 'localhost', #數據庫所在主機 'PORT': '3306', #數據庫端口 } } # mysite/__init__.py import pymysql pymysql.install_as_MySQLdb()
字段類型
字段約束
查詢
exact 表示判等 list = BookInfo.objects.filter(id__exact=1) list = BookInfo.objects.filter(id=1)
模糊查詢
contains 是否包含 list = BookInfo.objects.filter(btitle__contains='傳') list = BookInfo.objects.filter(btitle__icontains='傳') # 不區分大小寫
startswith 以指定字符開頭 list = BookInfo.objects.filter(btitle__startswith='神') list = BookInfo.objects.filter(btitle__istartswith='神') # 不區分大小寫
endswithch 以指定字符結尾 list = BookInfo.objects.filter(btitle__endswitch='侶') list = BookInfo.objects.filter(btitle__iendswitch='侶') # 不區分大小寫
空查詢
isnull 是否爲空 list = BookInfo.objects.filter(btitle__isnull=False)
範圍查詢
in 是否包含在範圍內 list = BookInfo.objects.filter(id__in=[1, 3, 5])
比較查詢
gt: 大於 gte: 大於等於 lt: 小於 lte:小於等於 list = BookInfo.objects.filter(id__gt=3)
不等於查詢
exclude() 不等於運算符 list = BookInfo.objects.exclude(id=3)
日期查詢
year、month、day、week_day、hour、minute、second list = BookInfo.objects.filter(bpub_date__year=1980)
F對象
比較一個對象中的兩個屬性 list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
Q對象
多個過濾器逐個調用表示邏輯與關係,同sql語句中where部分的and關鍵字 list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3) 若是想實現邏輯或的功能,就要使用到Q對象查詢,Q對象可使用&、|鏈接,&表示邏輯與,|表示邏輯或,~表示not list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))
聚合查詢
使用aggregate()過濾器調用聚合函數,聚合函數包括:Avg,Count,Max,Min,Sum list = BookInfo.objects.count()
查詢集表示從數據庫中查詢到的對象集合
返回查詢集的過濾器
返回單個值的過濾器
判斷一個查詢集中是否有數據
兩個特性
限制結果集
能夠對結果集進行切片操做,等同於數據庫中的分頁操做,可是不支持負數 list = BookInfo.objects.all()[0:2]
一對多
一本圖書中能夠對應多個英雄,因此圖書和英雄是一對多的關係 class BookInfo(models.Model): btitle = models.CharField(max_length=20) bpub_date = models.DateField() bread = models.IntegerField(default=0) bcomment = models.IntegerField(default=0) isDelete = models.BooleanField(default=False) class HeroInfo(models.Model): hname = models.CharField(max_length=20) hgender = models.BooleanField(default=True) isDelete = models.BooleanField(default=False) hcomment = models.CharField(max_length=200) hbook = models.ForeignKey('BookInfo')
多對多
一個類別中多條新聞,一條新聞也能夠分爲不一樣的類別,因此新聞是多對多關係 class TypeInfo(models.Model): tname = models.CharField(max_length=20) class NewsInfo(models.Model): ntitle = models.CharField(max_length=60) ncontent = models.TextField() npub_date = models.DateTimeField(auto_now_add=True) ntype = models.ManyToManyField('TypeInfo')
一端的對象.多端的類名_set b = BookInfo.objects.get(id=1) b.HeroInfo_set.all()
多端的模型對象.多端模型類的類關係字段 h = HeroInfo.objects.get(id=1) h.hbook
多對應的模型類對象.關聯類屬性_id h = HeroInfo.objects.get(id=1) h.book_id
語法: 關聯模型類名小寫__屬性名__條件運算符=值 list = BookInfo.objects.filter(heroinfo__hcontent__contains='八')
語法: 一模型類關聯屬性名__一模型類屬性名__條件運算符=值 list = HeroInfo.objects.filter(hbook__btitle='天龍八部')
視圖負責接受Web請求HttpRequest,進行邏輯處理,返回Web響應HttpResponse給請求者
位置參數
url(r'^delete(\d+)/$',views.show_arg),
關鍵字參數
url(r'^delete(?P<id1>\d+)/$',views.show_arg),
內置錯誤視圖,若是想看到錯誤視圖而不是調試信息的話,須要修改setting文件的DEBUG選項
# mysite/setting.py DEBUG = False ALLOWED_HOSTS = ['*', ]
屬性
方法
set_cookie:設置Cookie信息
某些網站爲了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據,Cookie是由服務器端生成,發送給User-Agent(通常是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器,Cookie名稱和值能夠由服務器端開發本身定義,這樣服務器能夠知道該用戶是不是合法用戶以及是否須要從新登陸等,服務器能夠利用Cookies包含信息的任意性來篩選並常常性維護這些信息,以判斷在HTTP傳輸中的狀態
Cookie特色
設置Cookie
def cookie_set(request): response = HttpResponse("<h1>設置Cookie,請查看響應報文頭</h1>") response.set_cookie('h1', '你好') return response
讀取Cookie
def cookie_get(request): response = HttpResponse("讀取Cookie,數據以下:<br>") if 'h1' in request.COOKIES: response.write('<h1>' + request.COOKIES['h1'] + '</h1>') return response
對於敏感、重要的信息,建議要儲在服務器端,不能存儲在瀏覽器中,如用戶名、餘額、等級、驗證碼等信息
禁用Session中間件
存儲方式
存儲在數據庫中,以下設置能夠寫,也能夠不寫,這是默認存儲方式 SESSION_ENGINE='django.contrib.sessions.backends.db' 存儲在緩存中:存儲在本機內存中,若是丟失則不能找回,比數據庫的方式讀寫更快 SESSION_ENGINE='django.contrib.sessions.backends.cache' 混合存儲:優先從本機內存中存取,若是沒有則從數據庫中存取 SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
依賴於Cookie
在使用Session後,會在Cookie中存儲一個sessionid的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid後,會根據這個值找出這個請求者的Session
對象及方法
以鍵值對的格式寫session request.session['鍵']=值 根據鍵讀取值 request.session.get('鍵',默認值) 清除全部session,在存儲中刪除值部分 request.session.clear() 清除session數據,在存儲中刪除session的整條數據 request.session.flush() 刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值 del request.session['鍵'] 設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時 request.session.set_expiry(value) 若是value是一個整數,會話將在value秒沒有活動後過時,若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時,若是value爲None,那麼會話永不過時
負責封裝構造要返回的html
語法:{{變量}}
解析順序:
for
{% for item in book_list %} 循環邏輯 {{forloop.counter}}表示當前是第幾回循環,從1開始 {%empty%}列表爲空執行此邏輯 {% end for %}
if
{%if ...%} 邏輯1 {%elif ...%} 邏輯2 {%else%} 邏輯3 {%endif%}
語法:變量|過濾器:參數
data|default:'默認值'
在應用中建立templatetags目錄
在該目錄下建立filters.py文件
#導入Library類 from django.template import Library #建立一個Library類對象 register=Library() #使用裝飾器進行註冊 @register.filter #定義求餘函數mod,將value對2求餘 def mod(value): return value%2 == 0
使用load標籤引入模塊
{%load filters%}
若是發如今多個模板中某些內容相同,那就應該把這段內容定義到父模板中
標籤block:用於在父模板中預留區域,留給子模板填充差別性的內容,名字不能相同
{%block 名稱%} 預留區域,能夠編寫默認內容,也能夠沒有默認內容 {%endblock 名稱%}
標籤extends:繼承,寫在子模板文件的第一行
{% extends "父模板路徑"%} {%block 名稱%} 實際填充內容 {{block.super}}用於獲取父模板中block的內容 {%endblock 名稱%}
跨站請求僞造,CSRF指***者盜用了你的身份,以你的名義發送惡意請求
CSRF可以作的事情:以你名義發送郵件,發消息,盜取你的帳號,甚至於購買商品,虛擬貨幣轉帳......
形成的問題:我的隱私泄露以及財產安全
若是想防止CSRF,首先是重要的信息傳遞都採用POST方式而不是GET方式
防止CSRF
保護原理
加入csrf_token這個標籤後,會想客戶端瀏覽器寫入一條cookie,還會在表單中加入一個隱藏域,裏面存放有一個value值,而後提交數據的時候,會將這兩個值提交到服務器進行校驗,若是value值cookie值相同,正常執行業務邏輯,不然,返回403錯誤
新用戶註冊,爲了防止請求過多,能夠加入驗證碼功能,若是驗證碼錯誤,不須要執行後續操做,減輕服務器的壓力
pip3 install Pillow
from PIL import Image, ImageDraw, ImageFont from django.utils.six import BytesIO ... def verify_code(request): #引入隨機函數模塊 import random #定義變量,用於畫面的背景色、寬、高 bgcolor = (random.randrange(20, 100), random.randrange( 20, 100), 255) width = 100 height = 25 #建立畫面對象 im = Image.new('RGB', (width, height), bgcolor) #建立畫筆對象 draw = ImageDraw.Draw(im) #調用畫筆的point()函數繪製噪點 for i in range(0, 100): xy = (random.randrange(0, width), random.randrange(0, height)) fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) draw.point(xy, fill=fill) #定義驗證碼的備選值 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' #隨機選取4個值做爲驗證碼 rand_str = '' for i in range(0, 4): rand_str += str1[random.randrange(0, len(str1))] #構造字體對象,ubuntu的字體路徑爲「/usr/share/fonts/truetype/freefont」 font = ImageFont.truetype('FreeMono.ttf', 23) #構造字體顏色 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) #繪製4個字 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) #釋放畫筆 del draw #存入session,用於作進一步驗證 request.session['verifycode'] = rand_str #內存文件操做 buf = BytesIO() #將圖片保存在內存中,文件類型爲png im.save(buf, 'png') #將內存中的圖片數據返回給客戶端,MIME類型爲圖片png return HttpResponse(buf.getvalue(), 'image/png')
url(r'^verify_code/$', views.verify_code),
def verify_show(request): return render(request,'app01/verify_show.html')
url(r'^verify_show/$', views.verify_show),
<html> <head> <title>驗證碼</title> </head> <body> <form method="post" action="/verify_yz/"> {%csrf_token%} <input type="text" name="yzm"> <img id="yzm" src="/verify_code/"/> <span id="change">看不清,換一個</span> <br> <input type="submit" value="提交"> </form> </body> </html>
def verify_yz(request): yzm=request.POST.get('yzm') verifycode=request.session['verifycode'] response=HttpResponse('no') if yzm==verifycode: response=HttpResponse('ok') return response
url(r'^verify_yz/$', views.verify_yz),
<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(r'^',include('app01.urls',namespace='app01')),
url(r'^fan2/$', views.fan2,name='fan2'),
<html> <head> <title>反向解析</title> </head> <body> 普通連接:<a href="/fan2/">fan2</a> <hr> 反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a> </body> </html>
url(r'^fan_show/$', views.fan2,name='fan2'),
from django.shortcuts import redirect from django.core.urlresolvers import reverse return redirect(reverse('app01:fan2'))
總結:在定義url時,須要爲include定義namespace屬性,爲url定義name屬性,使用時,在模板中使用url標籤,在視圖中使用reverse函數,根據正則表達式動態生成地址,減輕後期維護成本
內容發佈的部分由網站的管理員負責查看、添加、修改、刪除數據,開發這些重複的功能是一件單調乏味、缺少創造力的工做,爲此,Django可以根據定義的模型類自動地生成管理模塊
頁大小,每頁顯示多少條數據
list_per_page=100
操做選項的位置
actions_on_top=True 頂部顯示的屬性,True爲顯示,默認爲True,False即爲不顯示 actions_on_bottom=True 同上,只不過是底部顯示的屬性
字段排序
admin_order_field=[字段1,字段2]
列標題
short_description='列標題'
側邊欄過濾器
list_filter=[]
搜索框
search_fields=[]
中文標題
在模型類的字段爲其指定verbose_name
分組顯示
fieldset=( ('組1標題',{'fields':('字段1','字段2')}), ('組2標題',{'fields':('字段3','字段4')}), )
將模型的類型定義成ImageField字段
class Pic(models.Model): pic = models.ImageField(upload_to='app01/')
遷移
python managee.py makemigrations python manage.py migrate
設置圖片保存位置
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media") 而且在static建立media目錄,在meida目錄下建立應用名稱的目錄,此爲app01
在admin中註冊該模型類
admin.site.register(Pic)