Python全棧開發之Django基礎
No.1 MVC&MTV
MVC
M全拼為Model,主要封裝對數據庫層的訪問,對數據庫中的數據進行增、刪、改、查操作
V全拼為View,用於封裝結果,生成頁面展示的html內容
C全拼為Controller,用於接收請求,處理業務邏輯,與Model和View交互,返回結果
MTV
M全拼為Model,與MVC中的M功能相同,負責和數據庫交互,進行數據處理
V全拼為View,與MVC中的C功能相同,接收請求,進行業務處理,返回應答
T全拼為Template,與MVC中的V功能相同,負責封裝構造要返回的html
No.2 安裝與配置
虛擬環境
為什麽要使用虛擬環境?
如果在一臺機器上,想開發不同的項目,這些項目依賴的同一個包的版本不同,其他項目就無法正常運行了,所有我們要用到虛擬環境,虛擬環境就是對真實Python環境的復制,通過建立多個虛擬環境,在不同的虛擬環境中開發項目就實現了項目之間的間隔
創建虛擬環境
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
Django基本使用
創建項目
創建第一個項目
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)
No.3 模型
負責和數據庫交互,進行數據處理
ORM
什麽是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()
定義模型類
字段類型
- AutoField:自動增長的IntegerField,通常不用指定,不指定時Django會自動創建屬性名為id的自動增長屬性
- BooleanField: 布爾字段,值為True或False
- NullBooleanField: 支持Null,True,False
- CharField(max_length): 字符串,表示最大字符個數
- TextField: 大文本字段,字符超過4000使用
- IntgerField: 整數字段
- DecimalField(max_digits,decimal_places): 十進制浮點數,max_digits表示總位數,decimal_places表示小數位數
- FloatField: 浮點數
- DateField(auto_now,auto_now_add): auto_now表示每次保存對象時,自動設置該字段為當前時間,用於最後一次修改的時間戳,默認為False,auto_now_add表示當對象第一次創建時自動設置當前時間,用於創建時的時間戳,默認為False
- TimeField: 時間字段,同上
- 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
條件查詢
查詢
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()
查詢集
查詢集表示從數據庫中查詢到的對象集合
返回查詢集的過濾器
- all():返回所有數據
- filter(): 返回滿足條件的數據
- exclude(): 返回不滿足條件的數據
- order_by(): 對結果集排序
返回單個值的過濾器
- get(): 返回單個滿足條件的對象,如果未找到會拋出DoesNotExist異常,如果返回多條拋出MultipleObjectReturnned異常
- count(): 返回當前查詢結果的總條數
- aggregate(): 聚合,返回一個字典
判斷一個查詢集中是否有數據
兩個特性
- 惰性 創建查詢集不會訪問數據庫,直到調用數據時,才會訪問數據庫
- 緩存 使用同一個結果集,第一次使用會觸發查詢數據庫,然後將結果緩存下載,再次使用直接調用緩存
限制結果集
可以對結果集進行切片操作,等同於數據庫中的分頁操作,但是不支持負數
list = BookInfo.objects.all()[0:2]
關聯
關系字段類型
- ForeignKey:一對多,將字段定義在多的一端中
- ManyToManyField:多對多,將字段定義在任意一端中
- OneToOneField:一對一,將字段定義在任意一端中
- 可以維護遞歸的關聯關系,使用‘self‘指定,詳見"自關聯"
一對多
一本圖書中可以對應多個英雄,所以圖書和英雄是一對多的關系
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語法:
多對應的模型類對象.關聯類屬性_id
h = HeroInfo.objects.get(id=1)
h.book_id
通過模型類執行關聯查詢
- 由多模型類條件查詢一模型類數據:
語法:
關聯模型類名小寫__屬性名__條件運算符=值
list = BookInfo.objects.filter(heroinfo__hcontent__contains=‘八‘)
- 由一模型類條件查詢多模型類數據:
語法:
一模型類關聯屬性名__一模型類屬性名__條件運算符=值
list = HeroInfo.objects.filter(hbook__btitle=‘天龍八部‘)
No.4視圖
視圖負責接受Web請求HttpRequest,進行邏輯處理,返回Web響應HttpResponse給請求者
URLconf
位置參數
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 = [‘*‘, ]
HttpReqeust對象
- path: 一個字符串,表示請求的完整路徑,不包含域名和參數
- method: 一個字符串,表示請求方法,常用的有GET、POST
- encoding: 一個字符串,表示提交數據的編碼類型
- GET: QueryDict類型對象,類似於字典,包含get請求方式的所有參數
- POST:QueryDict類型對象,類似於字典,包含post請求方式的所有參數
- FILES:一個類似於字典的對象,包含所有的上傳文件
- COOKIES:一個標準的Python字典,包含所有的cookie,鍵和值都為字符串
- session:一個可讀寫的類似於字典的對象,表示當前的會話,只有當Django 啟用會話的支持時才可用
HttpResponse對象
屬性
- content:表示返回的內容。
- charset:表示response采用的編碼字符集,默認為utf-8。
- status_code:返回的HTTP響應狀態碼。
- content-type:指定返回數據的的MIME類型,默認為‘text/html‘。
方法
- init:創建HttpResponse對象後完成返回內容的初始化
-
set_cookie:設置Cookie信息
- delete_cookie(key):刪除指定的key的Cookie,如果key不存在則什麽也不發生
- write:向響應體中寫數據
Cookie
某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據,Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器,Cookie名稱和值可以由服務器端開發自己定義,這樣服務器可以知道該用戶是否是合法用戶以及是否需要重新登錄等,服務器可以利用Cookies包含信息的任意性來篩選並經常性維護這些信息,以判斷在HTTP傳輸中的狀態
Cookie特點
- Cookie以鍵值對的方式存儲數據
- Cookie基於域名安全,不同域名下的Cookie是不可以互相訪問的
- 當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的所以Cookiet提交給網站服務器
設置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中間件
存儲方式
存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式
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,那麽會話永不過期
No.5 模板
負責封裝構造要返回的html
模板語言
變量
語法:{{變量}}
解析順序:
- 字典book[‘title‘]
- 先屬性後方法,將book當作對象,先把title當作屬性,如果找不到會認為它是方法
- 如果格式是book 0,則解析為book[0]
標簽
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%}
模板繼承
父模板
如果發現在多個模板中某些內容相同,那就應該把這段內容定義到父模板中