1. DJANGO使用指南
Django簡介:
Django發(fā)布于2005年7月,是當前Python世界里最有名且成熟的網(wǎng)絡(luò)框架。 最初是被開發(fā)用于管理勞倫斯出版集團旗下的以新聞內(nèi)容為主的網(wǎng)站的,即CMS(內(nèi)容管理系統(tǒng))軟件。
Django是一個用Python編寫的開放源代碼的Web應用框架,代碼是開源的。此系統(tǒng)采用了MVC的框架模式, 也可以稱為MTV模式
什么是MVC模式
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計典范,用一種業(yè)務邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業(yè)務邏輯。MVC被獨特的發(fā)展起來用于映射傳統(tǒng)的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結(jié)構(gòu)中。 <b>通俗的來講就是,強制性的使應用程序的輸入,處理和輸出分開。</b>
<b>核心思想</b>:解耦
<b>優(yōu)點</b>:減低各個模塊之間的耦合性,方便變更,更容易重構(gòu)代碼,最大程度的實現(xiàn)了代碼的重用
MVC(Model, View, Controller)
Model: 即<font color=red>數(shù)據(jù)存取層</font>。用于封裝于應用程序的業(yè)務邏輯相關(guān)的數(shù)據(jù),以及對數(shù)據(jù)的處理。說白了就是模型對象負責在數(shù)據(jù)庫中存取數(shù)據(jù)
View: 即<font color=red>表現(xiàn)層</font>。負責數(shù)據(jù)的顯示和呈現(xiàn)。渲染的html頁面給用戶,或者返回數(shù)據(jù)給用戶。
Controller: 即<font color=red>業(yè)務邏輯層</font>。負責從用戶端收集用戶的輸入,進行業(yè)務邏輯處理,包括向模型中發(fā)送數(shù)據(jù),進行CRUD操作。
圖解:

瀏覽器中MVC的表現(xiàn)形式圖解:

Django的模式簡介
MVT模式
嚴格來說,Django的模式應該是MVT模式,本質(zhì)上和MVC沒什么區(qū)別,也是各組件之間為了保持松耦合關(guān)系,只是定義上有些許不同。
Model: 負責業(yè)務與數(shù)據(jù)庫(ORM)的對象
View: 負責業(yè)務邏輯并適當調(diào)用Model和Template
Template: 負責把頁面渲染展示給用戶
注意: Django中還有一個url分發(fā)器,也叫作路由。主要用于將url請求發(fā)送給不同的View處理,View在進行相關(guān)的業(yè)務邏輯處理。
2. VIRTUALENV虛擬環(huán)境創(chuàng)建指南
前言
本教程中使用到的python版本均為python3.x版本,由于本人安裝的是python3.6.3版本,所以一下的課程均是在此基礎(chǔ)上進行的。
-
virtualenv使用場景:當開發(fā)成員負責多個項目的時候,每個項目安裝的庫又是有很多差距的時候,會使用虛擬環(huán)境將每個項目的環(huán)境給隔離開來。
比如,在有一個老項目已經(jīng)開發(fā)維護了3年了,里面很多庫都是比較老的版本了。例如python使用的是2.7版本的。但是新項目使用的python版本是3.6的。為了解決這種項目執(zhí)行環(huán)境的沖突,所以引入了虛擬環(huán)境virtualenv。
當然除了virtualenv可以起到隔離環(huán)境的作用,還有其他技術(shù)方案來實現(xiàn),而且上線流程簡單,大大減輕運維人員的出錯率,比如每一個項目使用一個docker鏡像,在鏡像中去安裝項目所需的環(huán)境,庫版本等等
python環(huán)境的配置
- 在cmd中能通過python去啟動,如果不行直接跳到第三步

-
在cmd中能通過pip3啟動安裝軟件,如果不行直接跳到第三步
image.png
3.配置python環(huán)境和pip環(huán)境

確認pip安裝成功,如果Scritp文件夾下沒有pip可執(zhí)行文件,則執(zhí)行第五步。
由于python3.6安裝以后,在Scripts文件中沒有pip的可執(zhí)行軟件,需要輸入一下命令進行安裝
python -m ensurepip

注:現(xiàn)在在python的安裝文件夾Scripts下就有pip.exe以及easy_install.exe等可執(zhí)行文件了,就可以使用pip安裝啦~
windows中安裝使用
- 安裝virtualenv
pip install virtualenv

- 創(chuàng)建虛擬環(huán)境
先查看一下安裝虛擬環(huán)境有那些參數(shù),是必須填寫的

注意兩個參數(shù):
--no-site-packages和-p參數(shù)

virtualenv --no-site-packages venv
以下是指定安裝虛擬環(huán)境中的python版本的安裝方式:

- 進入/退出env
進入 cd env/Scripts/文件夾 在activate命令
退出 deactivate
在pycharm中創(chuàng)建項目方法

ubuntu中安裝使用
- 安裝virtualenv
apt-get install python-virtualenv
- 創(chuàng)建包含python3版本的虛擬環(huán)境
virtualenv -p /usr/bin/python3 env
env代表創(chuàng)建的虛擬環(huán)境的名稱
- 進入/退出env
進入 source env/bin/activate
退出 deactivate
-
pip使用
查看虛擬環(huán)境下安裝的所有的包
pip list查看虛擬環(huán)境重通過pip安裝的包
pip freeze
3. DJANGO使用指南
創(chuàng)建Django項目
cmd命令創(chuàng)建步項目驟步驟:
1、進入創(chuàng)建好的虛擬環(huán)境
2、去到需要放置項目的文件夾下,新建項目
3、創(chuàng)建好項目后拖動到pycharm中打開
直接用pycharm創(chuàng)建項目步驟:

1. 首先創(chuàng)建一個運行Django項目的虛擬環(huán)境(virtualenv)
虛擬環(huán)境的創(chuàng)建在基礎(chǔ)課程中講解,地址
該虛擬環(huán)境中有django庫,python3,pymysql等等需要的庫
大致在羅列下安裝了那些庫:
pip install Django==1.11
pip install PyMySQL
2. 創(chuàng)建一個Django項目
2.1 創(chuàng)建項目
django-admin startproject halloWorld
該命令是創(chuàng)建一個名為halloWorld的工程
項目目錄介紹
下面展示創(chuàng)建以后的文件,具體有哪些文件:

manage.py: 是Django用于管理本項目的管理集工具,之后站點運行,數(shù)據(jù)庫自動生成,數(shù)據(jù)表的修改等都是通過該文件完成。
init.py: 指明該目錄結(jié)構(gòu)是一個python包,暫無內(nèi)容,在后期會初始化一些工具會使用到。
seetings.py: Django項目的配置文件,其中定義了本項目的引用組件,項目名,數(shù)據(jù)庫,靜態(tài)資源,調(diào)試模式,域名限制等
urls.py:項目的URL路由映射,實現(xiàn)客戶端請求url由哪個模塊進行響應。
wsgi.py:定義WSGI接口信息,通常本文件生成后無需改動
2.2 運行Django項目
python manage.py runserver 端口
該命令是運行項目,端口可以不用寫,啟動的時候會默認隨機創(chuàng)建一個可以使用的端口
2.2 創(chuàng)建app
python manage.py startapp hallo_app
該命令是在blog工程下創(chuàng)建一個名為hallo_app的app
3. settings.py配置文件詳細解讀
a) 設(shè)置語言:
LANGUAGE_CODE = 'zh-hans' 表示中文
LANGUAGE_CODE = 'en-us' 表示英文

設(shè)置時區(qū): TIME_ZONE = 'Asia/Shanghai'
b) 時區(qū)解釋: (需要詳細回顧思考時區(qū)問題)
UTC:世界標準時間,也就是平常說的零時區(qū)。
北京時間表示東八區(qū)時間,即UTC+8
模型使用指南--admin
前言
Djang自身集成了管理后臺,在管理后臺中可以對我們自定義model進行CRUD操作,也能進行列表展示解析,分頁等等
使用admin管理后臺
0. 準備工作,在model中定義Student的模型
```
class Students(models.Model):
name = models.CharField(max_length=10)
sex = models.BooleanField()
class Meta:
db_table = 'student'
```
1. admin管理后臺的url
在工程目錄下可以看到路由配置中有一個admin的url地址
```
url(r'^admin/', admin.site.urls),
```
2. 創(chuàng)建admin后臺的用戶密碼
```
python manage.py createsuperuser
```
[圖片上傳失敗...(image-4a4434-1536808795504)]
3. 在登錄后的管理后臺中對自定義的模型進行CRUD操作
在管理后臺中操作模型對象。需要在app的admin.py中寫如下代碼
```
admin.site.register(模型名)
```
4. 繼承admin.ModelAdmin,編寫自定義的admin
```
class StudentAdmin(admin.ModelAdmin):
def set_sex(self):
if self.sex:
return '男'
else:
return '女'
set_sex.short_description = '性別'
list_display = ['id', 'name', set_sex]
list_filter = ['sex']
search_fields = ['name']
list_per_page = 1
admin.site.register(模型名, StudentAdmin)
```
其中:<br>
list_display: 顯示字段 <br>
list_filter: 過濾字段 <br>
search_fields: 搜索字段 <br>
list_per_page: 分頁條數(shù) <br>
5. 使用裝飾器去實現(xiàn)注冊
```
@admin.register(模型名)
class StudentAdmin(admin.ModelAdmin):
def set_sex(self):
if self.sex:
return '男'
else:
return '女'
set_sex.short_description = '性別'
list_display = ['id', 'name', set_sex]
list_filter = ['sex']
search_fields = ['name']
list_per_page = 1
```
模型使用指南--models
前言
Django對數(shù)據(jù)庫提供了很好的支持,對不同的數(shù)據(jù)庫,django提供了統(tǒng)一調(diào)用的API,我們可以根據(jù)不同的業(yè)務需求使用不同是數(shù)據(jù)庫。Django中引入了ORM(Objects Relational Mapping)對象關(guān)系映射,是一種程序技術(shù)。在下面會詳細的講解。
修改mysql配置
1. 在settings.py中配置數(shù)據(jù)庫連接信息
'ENGINE':'django.db.backends.mysql',
'NAME':'', #數(shù)據(jù)庫名
'USER':'', #賬號
'PASSWORD':'', #密碼
'HOST':'127.0.0.1', #IP(本地地址也可以是localhost)
'PORT':'3306', #端口
2. mysql數(shù)據(jù)庫中創(chuàng)建定義的數(shù)據(jù)庫
a) 進入mysql
mysql -u root -p
b) 創(chuàng)建數(shù)據(jù)庫
create database xxx charset=utf-8;
3. 配置數(shù)據(jù)庫鏈接
a) 安裝pymysql
pip install pymysql
b) 在工程目錄下的init.py文件中輸入,完成數(shù)據(jù)庫的驅(qū)動加載
import pymysql
pymysql.install_as_MySQLdb()
4. 定義模型,以及模型數(shù)據(jù)的增刪改查
重要概念:模型,表,屬性,字段
一個模型類在數(shù)據(jù)庫中對應一張表,在模型類中定義的屬性,對應模型對照表中的一個字段
定義屬性見定義屬性文件地址
創(chuàng)建學生模型類
class Student(models.Model):
s_name = models.CharField(max_length=10)
s_age = models.IntegerField()
s_gender = models.BooleanField()
class Meta:
db_table = 'cd_student'
ordering =[]
對象的默認排序字段,獲取對象列表時使用,升序ordering['id'],降序ordering['-id']
5.遷移數(shù)據(jù)庫
a) 生成遷移文件
python manage.py makemigrations
遷移成功會在migrations文件夾下生成0001_initial.py
注意:如果執(zhí)行后并沒有生成遷移文件,一直提示No changes detected這個結(jié)果的話,就要手動的去處理了。有兩點處理方式:
1) 先刪除掉pycache文件夾
2) 直接強制的去執(zhí)行遷移命令,python manage.py makemigrations xxx (xxx就是app的名稱)
3) 查看自動生成的數(shù)據(jù)庫,查看表django_migrations,刪掉app字段為xxx的數(shù)據(jù)(xxx就是app的名稱)
b) 執(zhí)行遷移生成數(shù)據(jù)庫
python manage.py migrate
注意: 生成遷移文件的時候,并沒有在數(shù)據(jù)庫中生成對應的表,而是執(zhí)行migrate命令之后才會在數(shù)據(jù)庫中生成表
6. ORM
ORM(Objects Relational Mapping)對象關(guān)系映射,是一種程序技術(shù),用于實現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換??梢院唵卫斫鉃榉g機。
可以理解為把面向?qū)ο蟮拇a,翻譯成數(shù)據(jù)庫可以看懂的SQL語句

7.模型查詢
a) 模型成員objects
Django默認通過模型的objects對象實現(xiàn)模型數(shù)據(jù)查詢
b) 過濾器
查詢集表示從數(shù)據(jù)庫獲取的對象集合
查詢集可以有多個過濾器
過濾器就是一個函數(shù),基于所給的參數(shù)限制查詢的結(jié)果
從SQL角度來說,查詢集合和select語句等價,過濾器就像where條件
Django有兩種過濾器用于篩選記錄
filter : 返回符合篩選條件的數(shù)據(jù)集
exclude : 返回不符合篩選條件的數(shù)據(jù)集
多個filter和exclude可以連接在一起查詢
當然還有如下這些過濾器:
all() 返回所有數(shù)據(jù)
filter() 返回符合條件的數(shù)據(jù)(數(shù)據(jù)可以有一個或者多個),條件可以有多個
例:類名.objects.filter(條件1,條件2...)
get() 返回符合條件的一條數(shù)據(jù),沒有數(shù)據(jù)會報錯,返回數(shù)據(jù)太多也報錯
exclude() 過濾掉符合條件的數(shù)據(jù)
order_by() 排序,
升序例:類名.objects.order_by(字段)
降序例:類名.objects.order_by(-字段)
values() 一條數(shù)據(jù)就是一個字典,返回一個列表
c) 查詢單個數(shù)據(jù)
get():返回一個滿足條件的對象。如果沒有返回符合條件的對象,會應該模型類DoesNotExist異常,如果找到多個,會引發(fā)模型類MultiObjectsReturned異常
first():返回查詢集中的第一個對象
last():返回查詢集中的最后一個對象
count():返回當前查詢集中的對象個數(shù)
exists():判斷查詢集中是否有數(shù)據(jù),如果有數(shù)據(jù)返回True,沒有返回False
d) 限制查詢集
限制查詢集,可以使用下表的方法進行限制,等同于sql中的limit
模型名.objects.all()[0:5] 下標不能為負數(shù);[:100]結(jié)束索引超出范圍不報錯;[100:]起始索引超出范圍也不報錯,返回空
e) 字段查詢
對sql中的where實現(xiàn),作為方法,filter(),exclude(),get()的參數(shù)
語法:屬性名稱__比較運算符 = 值
外鍵:屬性名_id
注意:like語句中使用%表示通配符。比如sql語句查詢 where name like '%xxx%',等同于filter(name_contains='xxx')
f) 比較運算符
contains:是否包含,大小寫敏感
例:模型名.objects.filter(字段名__contains='花'):模糊查詢名字中帶有‘花’的名字
startswith,endswith:以values開頭或者結(jié)尾,大小寫敏感
以上的運算符前加上i(ignore)就不區(qū)分大小寫了
例:模型名.objects.filter(字段名__startswith='花'):模糊查詢名字以‘花’開頭的名字
isnull,isnotnull:是否為空。
例:filter(name__isnull=True) :查詢名字為空的學生
in:是否包含在范圍內(nèi)。
例:filter(id__in=[1,2,3]) :查詢id在123的
gt,gte,lt,lte:大于,大于等于,小于,小于等于。
例:filter(age__gt=10) :查詢年齡大于10
pk:代表主鍵,也就是id。
例:filter(pk=1) :查詢id為1的
g) 聚合函數(shù)
aggregate()函數(shù)返回聚合函數(shù)的值
Avg:平均值
Count:數(shù)量
Max:最大
Min:最小
Sum:求和
例如: Student.objects.aggregate(Max('age'))
h) F對象/Q對象
<b>F對象:</b>可以使用模型的A屬性與B屬性進行比較
背景:在模型中有兩個字段,分別表示學生成績A與成績B,要對成績AB進行比較計算,就需要使用到F對象。
例如有如下例子1:
班級中有女生個數(shù)字段以及男生個數(shù)字段,統(tǒng)計女生數(shù)大于男生數(shù)的班級可以如下操作:
grades = Grade.objects.filter(girlnum__gt=F('boynum'))
F對象支持算數(shù)運算
grades = Grade.objects.filter(girlnum__gt=F('boynum') + 10)
例子2:
查詢python班下語文成績超過數(shù)學成績10分的學生
grade = Grade.objects.filter(g_name='python').first()
students = grade.student_set.all()
stu = students.filter(s_yuwen__gt= F('s_shuxue') + 10)
<b>Q對象:</b>Q()對象就是為了將過濾條件組合起來
當我們在查詢的條件中需要組合條件時(例如兩個條件“且”或者“或”)時。我們可以使用Q()查詢對象
使用符號&或者|將多個Q()對象組合起來傳遞給filter(),exclude(),get()等函數(shù)
Q()對象的前面使用字符“~”來代表意義“非”
例子1:
查詢學生中不是12歲的或者姓名叫張三的學生
student = Student.objects.filter(~Q(age=12) | Q(name='張三'))
例子2:
查詢python班語文小于80并且數(shù)學小于等于80的學生
grade = Grade.objects.filter(g_name='python').first()
students = grade.student_set.all()
stu = students.filter(~Q(s_yuwen__gte=80) & Q(s_shuxue__lte=80))
例子3:
查詢python班語文大于等于80或者數(shù)學小于等于80的學生
grade = Grade.objects.filter(g_name='python').first()
students = grade.student_set.all()
stu = students.filter(Q(s_yuwen__gte=80) | Q(s_shuxue__lte=80))
delete刪除字段
例:模型名.objects.filter(s_name='小草').filter().delete() :將第一個名字為小草的人刪除
update更新數(shù)據(jù)
例:模型名.objects.filter(id=1).update(s_name='大大'):將id為1的名字改為‘大大’
8.模型字段定義屬性
定義屬性
概述
·django根據(jù)屬性的類型確定以下信息
·當前選擇的數(shù)據(jù)庫支持字段的類型
·渲染管理表單時使用的默認html控件
·在管理站點最低限度的驗證
·django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設(shè)置某屬性為主鍵列后,則django不會再生成默認的主鍵列
·屬性命名限制
·遵循標識符規(guī)則(不使用python預定義的標識符號,內(nèi)置函數(shù)名,異常等。避免使用下劃線等)
·由于django的查詢方式,不允許使用連續(xù)的下劃線
庫
·定義屬性時,需要字段類型,字段類型被定義在django.db.models.fields目錄下,為了方便使用,被導入到django.db.models中
·使用方式
·導入from django.db import models
·通過models.Field創(chuàng)建字段類型的對象,賦值給屬性
邏輯刪除
·對于重要數(shù)據(jù)都做邏輯刪除,不做物理刪除,實現(xiàn)方法是定義isDelete屬性,類型為BooleanField,默認值為False
字段類型
·AutoField
·一個根據(jù)實際ID自動增長的IntegerField,通常不指定如果不指定,一個主鍵字段將自動添加到模型中
·CharField(max_length=字符長度)
·字符串,默認的表單樣式是 TextInput
·TextField
·大文本字段,一般超過4000使用,默認的表單控件是Textarea
·IntegerField
·整數(shù)
·DecimalField(max_digits=None, decimal_places=None)
·使用python的Decimal實例表示的十進制浮點數(shù)
·參數(shù)說明
·DecimalField.max_digits
·位數(shù)總數(shù)
·DecimalField.decimal_places
·小數(shù)點后的數(shù)字位數(shù)
·FloatField
·用Python的float實例來表示的浮點數(shù)
·BooleanField
·true/false 字段,此字段的默認表單控制是CheckboxInput
·NullBooleanField
·支持null、true、false三種值
·DateField([auto_now=False, auto_now_add=False])
·使用Python的datetime.date實例表示的日期
·參數(shù)說明
·DateField.auto_now
·每次保存對象時,自動設(shè)置該字段為當前時間,用于"最后一次修改"的時間戳,它總是使用當前日期,默認為false
·DateField.auto_now_add
·當對象第一次被創(chuàng)建時自動設(shè)置當前時間,用于創(chuàng)建的時間戳,它總是使用當前日期,默認為false
·說明
·該字段默認對應的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日歷控件,和一個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
·注意
·auto_now_add, auto_now, and default 這些設(shè)置是相互排斥的,他們之間的任何組合將會發(fā)生錯誤的結(jié)果
·TimeField
·使用Python的datetime.time實例表示的時間,參數(shù)同DateField
·DateTimeField
·使用Python的datetime.datetime實例表示的日期和時間,參數(shù)同DateField
·FileField
·一個上傳文件的字段
·ImageField
·繼承了FileField的所有屬性和方法,但對上傳的對象進行校驗,確保它是個有效的image
字段選項
·概述
·通過字段選項,可以實現(xiàn)對字段的約束
·在字段對象時通過關(guān)鍵字參數(shù)指定
·null
·如果為True,則該字段在數(shù)據(jù)庫中是空數(shù)據(jù),默認值是 False
·blank
·如果為True,則該字段允許為空白,默認值是 False
·注意
·null是數(shù)據(jù)庫范疇的概念,blank是表單驗證證范疇的
·db_column
·字段的名稱,如果未指定,則使用屬性的名稱
·db_index
·若值為 True, 則在表中會為此字段創(chuàng)建索引
·default
·默認值
·primary_key
·若為 True, 則該字段會成為模型的主鍵字段
·unique
·如果為 True, 這個字段在表中必須有唯一值
模型練習指南
前言
通過講mysql的系統(tǒng),翻譯一遍,在django中通過創(chuàng)建model去和數(shù)據(jù)庫中的表進行一一映射,并且通過ORM封裝
的處理方式去練習這一到習題,并寫出如下的解題答案
1.數(shù)據(jù)庫準備
在model中定義數(shù)據(jù)庫,其中的性別,男的存1,女的存0。
```
class Student(models.Model):
stuname = models.CharField(max_length=20)
studex = models.BooleanField()
stubirth = models.DateField()
stutel = models.CharField(max_length=255)
class Meta:
db_table = 'student'
```
2.數(shù)據(jù)庫遷移
python manage.py makemigrations
python manage.py migrate
3. 數(shù)據(jù)插入
3.1 使用表單form提交post請求數(shù)據(jù)
<form action="/app/addStu/" method="post">
stuname: <input type="text" name="name">
stusex: <input type="text" name="sex">
stubirth: <input type="date" name="birth">
stutel: <input type="text" name="tel">
<input type="submit" value="提交">
</form>
3.2 獲取post請求,獲取請求數(shù)據(jù),并且創(chuàng)建數(shù)據(jù)
stu = Student()
stu.stuname = stuname
stu.stusex = sex
stu.stubirth = birth
stu.stutel = tel
stu.save()
方法2:
Student.objects.create(stuname=stuname, stusex=sex, stubirth=birth, stutel=tel)
4. 查詢所有的學生信息
使用all()方法獲取所有的數(shù)據(jù)
Student.objects.all()
4. 查詢所有女學生的姓名和出生日期
Student.objects.filter(stusex=0)
或者
Student.objects.exclude(stusex=1)
其中:
filter():返回符合條件的數(shù)據(jù)
exclude():過濾掉符合條件的數(shù)據(jù)
5.查詢所有的學生,按照id從大到小排序
Student.objects.all().order_by('-id')
其中:
order_by('id'):表示按照id升序的排列
order_by('-id'):表示按照id降序的排列
6. 查詢單個數(shù)據(jù),就不做演示了,可以使用一下的方法去獲取
get():返回一個滿足條件的對象。如果沒有返回符合條件的對象,會應該模型類DoesNotExist異常,如果找到多個,會引發(fā)模型類MultiObjectsReturned異常
first():返回查詢集中的第一個對象
last():返回查詢集中的最后一個對象
count():返回當前查詢集中的對象個數(shù)
exists():判斷查詢集中是否有數(shù)據(jù),如果有數(shù)據(jù)返回True,沒有返回False
7.查詢所有80后學生的姓名、性別和出生日期(篩選)
Student.objects.filter(stubirth__gte='1980-01-01', stubirth__lte='1990-01-01')
8.查詢名字中有王字的學生的姓名(模糊)
Student.objects.filter(stuname__contains='王')
9.查詢姓王的學生姓名和性別(模糊)
Student.objects.filter(stuname__startswith='王')
思考:以什么結(jié)束應該怎么寫----》 使用endswith
模型加餐使用指南
前言
該文檔中主要介紹模型的對應關(guān)系,一對一,一對多,以及多對多的關(guān)系。并且舉例說明
模型對應關(guān)系描述如下:
1:1 一對一 OneToOneField :關(guān)聯(lián)代碼兩個模型都可以寫
1:N 一對多 ForeignKey :關(guān)聯(lián)代碼必須寫到多的模型中(如:一個班級有多個學生,那么關(guān)聯(lián)代碼必須寫到班級模型中)
M:N 多對多 ManyToManyField:關(guān)聯(lián)代碼兩個模型都可以寫,多對多遷移后django會自動創(chuàng)建好中間表;add添加;remove刪除
常見的幾種數(shù)據(jù)關(guān)系,django都提供了很好的支持
1. 一對一
1.1 模型
創(chuàng)建學生的模型:
class Student(models.Model):
stu_name = models.CharField(max_length=6, unique=True)
stu_sex = models.BooleanField(default=0)
stu_birth = models.DateField()
stu_delete = models.BooleanField(default=0)
stu_create_time = models.DateField(auto_now_add=True)
stu_operate_time = models.DateField(auto_now=True)
stu_tel = models.CharField(max_length=11)
stu_yuwen = models.DecimalField(max_digits=3, decimal_places=1, default=0)
stu_shuxue = models.DecimalField(max_digits=3, decimal_places=1, default=0)
class Meta:
db_table = 'stu'
創(chuàng)建學生拓展的模型:
class StuInfo(models.Model):
stu_addr = models.CharField(max_length=30)
stu_age = models.IntegerField()
stu = models.OneToOneField(Student)
class Meta:
db_table = 'stu_info'
使用models.OneToOneField()進行關(guān)聯(lián)
class StuInfo(models.Model):下是通過班級獲取學生信
stu = models.OneToOneField(Student)
注意:在數(shù)據(jù)中關(guān)聯(lián)字段名稱叫stu_id
1.2 通過學生拓展表去獲取學生信息
```
stuinfo = StuInfo.objects.all().first()
student = stuinfo.stu
```
注意:通過拓展表去獲取學生的信息的話,語法如下;
學生拓展表的單條對象.關(guān)聯(lián)字段,即可獲取到學生表的數(shù)據(jù)
1.3 通過學生獲取人信息1
```
stu = Student.objects.all().first()
stuInfo = stu.stuinfo
```
注意:通過學生獲取關(guān)聯(lián)表的數(shù)據(jù)的話,語法如下:
學生對象.關(guān)聯(lián)的表名,即可獲取到關(guān)聯(lián)表的數(shù)據(jù)
1.3.1 通過學生獲取人信息2
在關(guān)聯(lián)字段OneToOneField中加入?yún)?shù)related_name='xxx'
```
在
stu = Student.objects.all().first()
stuInfo = stu.xxx
```
注意:通過學生獲取關(guān)聯(lián)表的數(shù)據(jù)的話,語法如下:
學生對象.關(guān)聯(lián)的字段中定義的related_name參數(shù),即可獲取到關(guān)聯(lián)表的數(shù)據(jù)
1.4 設(shè)置對應關(guān)系的字段為保護模式 :
models.CASCADE 默認值
models.PROTECT 保護模式
models.SET_NULL 置空模式
models.SET_DETAULT 置默認值
models.SET() 刪除的時候吃重新動態(tài)指向一個實體訪問對象元素
on_delete = models.PROTECT
```
修改on_delete參數(shù)
models.OneToOneField('Student', on_delete=models.SET_NULL, null=True)
```
在刪除student對象的時候,stuinfo的關(guān)聯(lián)字段會設(shè)置為空null=True,如下命令去刪除student的數(shù)據(jù):
```
Student.objects.filter(id=1).delete()
```
1.5 定義on_delete=models.PROTECT
p = Student.objects.all().first()
p.delete()
注意:這個時候去執(zhí)行該業(yè)務邏輯的方法的時候會報錯

2. 一對多
2.1 模型
```
定義一個班級類還有學生類,實現(xiàn)一對多的關(guān)系:
先定義班級類
Class Grade(models.Model):
g_name = models.CharField(max_length=16)
定義student
class Student:
s_name = models.CharField(max_length=10)
s_age = models.IntegerField(default=1)
s_grade = models.ForeignKey(Grade, on_delete=PROTECT)
```
注意:使用models.ForeignKey關(guān)聯(lián)
獲取對象元素 grade.student_set
2.2 獲取數(shù)據(jù)
語法:通過一獲取多的數(shù)據(jù)
公式: <b>一的對象.多的模型名小寫_set</b>
然后在獲取數(shù)據(jù)all(), get(), filter() 等等
如下先通過學生去獲取班級信息:
stu = Student.objects.first()
stu.s_grade
如下是通過班級獲取學生信息:
g = Grade.objects.all().first()
g.stugrade.all() ---> 其中stugrade是定義的related_name參數(shù)
重點:
定義了related_name字段以后,只能通過related_name去反向獲取數(shù)據(jù),在也不能通過_set方法去獲取數(shù)據(jù)了
2.3 數(shù)據(jù)查詢,正查/反查
# 查詢id=4的學生的班級名稱
stu = Student.objects.get(id=4)
grade = stu.s_grade
# 查詢id=1的班級的所有學生
grade = Grade.objects.filter(id=1).first()
stus = grade.student_set.all()
2.4 練習題
2.6 獲取python班下的所有學生的信息
gs = Grade.objects.filter(g_name='python')[0]
allstu = gs.student_set.all()
2.7 獲取python班下語文成績大于80分的女學生
gs = Grade.objects.filter(g_name='python')[0]
allstu = gs.student_set.filter(stu_yuwen__gte=80)
2.8 獲取python班下語文成績超過數(shù)學成績10分的男學生
gs = Grade.objects.filter(g_name='python')[0]
allstu = gs.student_set.filter(stu_yuwen__gte=F('stu_shuxue') + 10)
2.9 獲取出生在80后的男學生,查看他們的班級
gs = Grade.objects.filter(g_name='python')[0]
allstu = gs.student_set.filter(stu_birth__gte='1980-01-01', stu_birth__lte='1990-01-01')
3. 多對多
3.1 M:N 模型
定義購物車,用戶的例子實現(xiàn)多對多:
```
1. 創(chuàng)建用戶模型:
class GoodsUser(models.Model):
u_name = models.CharField(max_length=32)
2. 創(chuàng)建商品模型:
class Goods(models.Model):
g_name = models.CharField(max_length=32)
g_user = models.ManyToManyField(User)
```
3.2 多對多表結(jié)構(gòu)
多對多關(guān)系:
1. 生成表的時候會多生成一張表(實際會有三張表)
2. 生成的表是專門用來維護關(guān)系的
3. 生成的表是使用兩個外鍵來維護多對多的關(guān)系
4. 兩個一對多的關(guān)系來實現(xiàn)多對多的實現(xiàn)
5. 刪除一個表的數(shù)據(jù)的話,中間關(guān)聯(lián)表也要刪除相關(guān)的信息
3.3 中間表數(shù)據(jù)的增(add)刪(remove)
# id=4的用戶添加兩個商品(id=1,2)
g_user = GoodsUser.objects.get(id=4)
c1 = Goods.objects.get(id=1)
c2 = Goods.objects.get(id=2)
g_user.goods_set.add(c1)
g_user.goods_set.add(c2)
# 刪除id=4的用戶的商品中id=1的商品
g_user.goods_set.remove(c1)
3.4 練習題
3.4.1 獲取第一個用戶購買了那些商品
```
gu = GoodsUser.objects.all().first()
allstu = gu.goods_set.all()
```
3.4.2 獲取指定商品的購買用戶信息
```
g = Goods.objects.filter(id=1)[0]
g.g_user.all()
```
模板使用指南
前言
在Django框架中,模板是可以幫助開發(fā)者快速生成呈現(xiàn)給用戶頁面的工具
模板的設(shè)計方式實現(xiàn)了我們MVT重VT的解耦,VT有著N:M的關(guān)系,一個V可以調(diào)用任意T,一個T可以供任意V使用
模板處理分為兩個過程
加載
渲染
1. 加載靜態(tài)配置文件
在settings.py中最底下有一個叫做static的文件夾,主要用來加載一些模板中用到的資源,提供給全局使用
這個靜態(tài)文件主要用來配置css,html,圖片,文字文件等
STATIC_URL = ‘/static/’
STATICFILES_DIRS = [
os.path.join(BASE_DIR, ‘static’)
]
只后在模板中,首先加載靜態(tài)文件,之后調(diào)用靜態(tài),就不用寫絕對全路徑了
2. 使用靜態(tài)配置文件
a) 加載渲染靜態(tài)配置文件
模板中聲明
{% load static %} 或者 {% load staticfiles %}
在引用資源的時候使用
{% static ‘xxx’ %} xxx就是相當于staticfiles_dirs的一個位置
b) 直接定義靜態(tài)配置
<img src="/static/images/mvc.png">
其中: 展示static文件夾下有一個images文件夾,下面有一個mvc.png的圖片
3. 模板摘要
3.1 模板主要有兩個部分
HTML靜態(tài)代碼
動態(tài)插入的代碼段(挖坑,填坑)也就是block
3.2 動態(tài)填充
模板中的動態(tài)代碼斷除了做基本的靜態(tài)填充,還可以實現(xiàn)一些基本的運算,轉(zhuǎn)換和邏輯
如下:

模板中的變量:
視圖傳遞給模板的數(shù)據(jù)
標準標識符規(guī)則
語法 {{ var }}
如果變量不存在,則插入空字符串
3.3 模板重的點語法
對象.屬性或者方法
索引 (student.0.name)

3.4模板中的小弊端
調(diào)用對象的方法,不能傳遞參數(shù)
3.5 模板的標簽
語法 {% tag %}
作用 a)加載外部傳入的變量
b)在輸出中創(chuàng)建文本
c)控制循環(huán)或邏輯
4. if表達式
格式1:
{% if 表達式 %}
{% endif %}
格式2:
{% if表達式 %}
{% else %}
{% endif %}
格式3:
{% if表達式 %}
{% elif 表達式 %}
{% endif %}

5. for表達式
格式1:
{% for 變量 in 列表 %}
{% empty %}
{% endfor %}

注意:當列表為空或者不存在時,執(zhí)行empty之后的語句
注意一下用法:
{{ forloop.counter }} 表示當前是第幾次循環(huán),從1開始
{{ forloop.counter0 }} 表示當前從第幾次循環(huán),從0開始
{{forloop.revcounter}}表示當前是第幾次循環(huán),倒著數(shù)數(shù),到1停
{{forloop.revcounter0}}表示當前是第幾次循環(huán),倒著數(shù)數(shù),到0停
{{forloop.first}}是否是第一個 布爾值
{{forloop.last}}是否是最后一個 布爾值
6. 注釋
6.1 注釋可見,可運行
<!-- 注釋內(nèi)容 -->
6.1 單行注釋注釋不可見,不可運行
單行注釋(頁面源碼中不會顯示注釋內(nèi)容)
{# 被注釋掉的內(nèi)容 #}
6.2 多行注釋注釋不可見,不可運行
{% comment %}
{% endcomment %}

7. 過濾器
引入過濾器定義:{{var|過濾器}}, 作用:在變量顯示前修改
過濾器有很多,比如add / lower / upper
7.1 加法
{{ p.page | add:5 }}
沒有減法的過濾器,但是加法里面可以加負數(shù)
{{ p.page | add: -5 }}
7.2 修改大小寫
lower / upper : {{ p.pname | lower }} 變?yōu)樾懟蛘叽髮?
7.3 傳參數(shù)
過濾器可以傳遞參數(shù),參數(shù)需要使用引號引起來。比如join: {{ student | join ‘=’ }}
如果值為空則設(shè)置默認值:
默認值:default,格式{{ var | default value }}
如果變量沒有被提供或者為False,空,會使用默認值
7.4 定制日期格式
根據(jù)制定格式轉(zhuǎn)換日期為字符串,處理時間的就是針對date進行的轉(zhuǎn)換
{{ dateVal | date: ‘y-m-d h:m:s’ }}
如果過濾器,定義為小寫的y,則返回的數(shù)據(jù)為兩位的年。如果寫的是大寫的Y,則返回的是四位的年
定義小寫的m,則返回數(shù)字的月份,如果定義大寫的M,則返回英文
定義小寫的h,則返回12小時制度的時,如果定義的是大寫的H,則返回24小時制度的時
7.5 是否轉(zhuǎn)義
HTML轉(zhuǎn)義:
將接收到的數(shù)據(jù)當成普通字符串處理還是當成HTML代碼來渲染的一個問題
渲染成html: {{ code | safe }}
還可以使用autoscape渲染:
{{ autoscape off }}
{{ endautoscape }}
不渲染的話:
{{ autoscape on }}
{{ endautoscape }}
7.6 案例
<!--1. 字符串‘Python’轉(zhuǎn)化為大寫,輸出結(jié)果為:PYTHON-->
{{ 'Python'|upper }}
<!--2. 字符串‘PYTHON’轉(zhuǎn)化為小寫,輸出結(jié)果為:python-->
{{ 'PYTHON'|lower }}
<!--3. 變量3增加4,輸出結(jié)果為:7-->
{{ 3|add:'4' }}
<!--4. 第一個字符轉(zhuǎn)化成大寫形式,輸出結(jié)果為:Python-->
{{ 'python'|capfirst }}
<!--5. 刪除指定符號的值,輸出結(jié)果為:studypythonisveryhappy -->
{{ 'study python is very happy'|cut:' ' }}
<!--6. 輸出缺省值,輸出結(jié)果為:nothing-->
{{ ''|default:'nothing' }}
<!--7. 返回第一個元素,輸出結(jié)果為:p-->
{{ 'python'|first }}
<!--8. 返回最后一個元素,輸出結(jié)果為:n-->
{{ 'python'|last }}
<!--9. 計算長度,輸出結(jié)果為:6-->
{{ 'python'|length }}
<!--10. 隨機一個元素,輸出隨機結(jié)果為:y-->
{{ 'python'|random }}
7.7 django內(nèi)建過濾器大全
1、add :將value的值增加2。使用形式為:{{ value | add: "2"}}。
2、addslashes:在value中的引號前增加反斜線。使用形式為:{{ value | addslashes }}。
3、capfirst:value的第一個字符轉(zhuǎn)化成大寫形式。使用形式為:{{ value | capfirst }}。
4、cut:從給定value中刪除所有arg的值。使用形式為:{{ value | cut:arg}}。
5、date: 格式化時間格式。使用形式為:{{ value | date:"Y-m-d H:M:S" }}
6、default:如果value是False,那么輸出使用缺省值。使用形式:{{ value | default: "nothing" }}。例如,如果value是“”,那么輸出將是nothing
7、default_if_none:如果value是None,那么輸出將使用缺省值。使用形式:{{ value | default_if_none:"nothing" }},例如,如果value是None,那么輸出將是nothing
8、dictsort:如果value的值是一個字典,那么返回值是按照關(guān)鍵字排序的結(jié)果
使用形式:{{ value | dictsort:"name"}},例如,
如果value是:
[{'name': 'python'},{'name': 'java'},{'name': 'c++'},]
那么,輸出是:
[{'name': 'c++'},{'name': 'java'},{'name': 'python'}, ]
9、dictsortreversed:如果value的值是一個字典,那么返回值是按照關(guān)鍵字排序的結(jié)果的反序。使用形式:與dictsort過濾器相同。
10、divisibleby:如果value能夠被arg整除,那么返回值將是True。使用形式:{{ value | divisibleby:arg}},如果value是9,arg是3,那么輸出將是True
11、escape:替換value中的某些字符,以適應HTML格式。使用形式:{{ value | escape}}。例如,< 轉(zhuǎn)化為 <> 轉(zhuǎn)化為 >' 轉(zhuǎn)化為 '" 轉(zhuǎn)化為 "
13、filesizeformat:格式化value,使其成為易讀的文件大小。使用形式:{{ value | filesizeformat }}。例如:13KB,4.1MB等。
14、first:返回列表/字符串中的第一個元素。使用形式:{{ value | first }}
16、iriencode:如果value中有非ASCII字符,那么將其進行轉(zhuǎn)化成URL中適合的編碼,如果value已經(jīng)進行過URLENCODE,改操作就不會再起作用。使用形式:{{value | iriencode}}
17、join:使用指定的字符串連接一個list,作用如同python的str.join(list)。使用形式:{{ value | join:"arg"}},如果value是['a','b','c'],arg是'//'那么輸出是a//b//c
18、last:返回列表/字符串中的最后一個元素。使用形式:{{ value | last }}
19、length:返回value的長度。使用形式:{{ value | length }}
20、length_is:如果value的長度等于arg的時候返回True。使用形式:{{ value | length_is:"arg"}}。例如:如果value是['a','b','c'],arg是3,那么返回True
21、linebreaks:value中的"\n"將被<br/>替代,并且整個value使用</p>包圍起來。使用形式:{{value|linebreaks}}
22、linebreaksbr:value中的"\n"將被<br/>替代。使用形式:{{value |linebreaksbr}}
23、linenumbers:顯示的文本,帶有行數(shù)。使用形式:{{value | linenumbers}}
24、ljust:在一個給定寬度的字段中,左對齊顯示value。使用形式:{{value | ljust}}
25、center:在一個給定寬度的字段中,中心對齊顯示value。使用形式:{{value | center}}
26、rjust::在一個給定寬度的字段中,右對齊顯示value。使用形式:{{value | rjust}}
27、lower:將一個字符串轉(zhuǎn)換成小寫形式。使用形式:{{value | lower}}
30、random:從給定的list中返回一個任意的Item。使用形式:{{value | random}}
31、removetags:刪除value中tag1,tag2....的標簽。使用形式:{{value | removetags:"tag1 tag2 tag3..."}}
32、safe:當系統(tǒng)設(shè)置autoescaping打開的時候,該過濾器使得輸出不進行escape轉(zhuǎn)換。使用形式:{{value | safe}}
33、safeseq:與safe基本相同,但有一點不同的就是:safe是針對字符串,而safeseq是針對多個字符串組成的sequence
34、slice:與python語法中的slice相同。使用形式:{{some_list | slice:"2"}}
37、striptags:刪除value中的所有HTML標簽.使用形式:{{value | striptags}}
38、time:格式化時間輸出。使用形式:{{value | time:"H:i"}}或者{{value | time}}
39、title:轉(zhuǎn)換一個字符串成為title格式。
40、truncatewords:將value切成truncatewords指定的單詞數(shù)目。使用形式:{{value | truncatewords:2}}。例如,如果value是Joel is a slug 那么輸出將是:Joel is ...
42、upper:轉(zhuǎn)換一個字符串為大寫形式
43、urlencode:將一個字符串進行URLEncode
46、wordcount:返回字符串中單詞的數(shù)目
8. 運算
8.1 乘
{% widthratio 數(shù) 分母 分子 %}
如下例子: 求數(shù)學成績的10倍的結(jié)果
{% widthratio 10 1 stu.stu_shuxue %}
8.2 整除
{{ num|divisibleby:2 }}
注意:該語句的意思是,判斷num值是否能被2整除,如果能的話返回True,不能的話返回False
8.3 ifeuqal判斷相等
{% ifequal value1 value2 %}
{% endifqueal %}

9. 反向解析
Url 反向解析
{% url ‘namespace:name’ p1 p2 %}

10. 跨站請求CSRF(Cross Site Request Forgery)
csrf攻擊說明
1.用戶C打開瀏覽器,訪問受信任網(wǎng)站A,輸入用戶名和密碼請求登錄網(wǎng)站A;
2.在用戶信息通過驗證后,網(wǎng)站A產(chǎn)生Cookie信息并返回給瀏覽器,此時用戶登錄網(wǎng)站A成功,可以正常發(fā)送請求到網(wǎng)站A;
3.用戶未退出網(wǎng)站A之前,在同一瀏覽器中,打開一個TAB頁訪問網(wǎng)站B;
4.網(wǎng)站B接收到用戶請求后,返回一些攻擊性代碼,并發(fā)出一個請求要求訪問第三方站點A;
5.瀏覽器在接收到這些攻擊性代碼后,根據(jù)網(wǎng)站B的請求,在用戶不知情的情況下攜帶Cookie信息,向網(wǎng)站A發(fā)出請求。網(wǎng)站A并不知道該請求其實是由B發(fā)起的,所以會根據(jù)用戶C的Cookie信息以C的權(quán)限處理該請求,導致來自網(wǎng)站B的惡意代碼被執(zhí)行。
csrf的攻擊之所以會成功是因為服務器端身份驗證機制可以通過Cookie保證一個請求是來自于某個用戶的瀏覽器,但無法保證該請求是用戶允許的。因此,預防csrf攻擊簡單可行的方法就是在客戶端網(wǎng)頁上添加隨機數(shù),在服務器端進行隨機數(shù)驗證,以確保該請求是用戶允許的。Django也是通過這個方法來防御csrf攻擊的。
理解如下圖:

Django中防止跨站請求偽造使用CSRF, 即:客戶端訪問服務器端,在服務器端正常返回給客戶端數(shù)據(jù)的時候,而外返回給客戶端一段字符串,等到客戶端下次訪問服務器
端時,服務器端會到客戶端查找先前返回的字符串,如果找到則繼續(xù),找不到就拒絕。
Django中配置:
- 在表單中添加
{% csrf_token %} - 在settings中的中間件MIDDLEWARE中配置打開
‘django.middleware.csrf.CsrfViewMiddleware’
11. 模板繼承
11.1 block挖坑不用看了
關(guān)鍵字 block挖坑
{% block xxx %}
{% endblock %}
11.2 extends
extends 繼承,寫在開頭位置
{% extends ‘父模板路徑’%}
11.3 include
include 加載模型進行渲染
{% include ‘模板文件’%}
12. 模板繼承實戰(zhàn)
12.1 定義基礎(chǔ)模板base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
{% endblock %}
</title>
{% block extCSS %}
{% endblock %}
{% block extJS %}
{% endblock %}
</head>
{% block indexbody %}
{% endblock %}
<body>
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
</body>
</html>
12.2 定義繼承base.html的base_main.html模板
該base_main.html模板主要用于加載一些公共的js或者css,其余模板繼承該模板后,可以直接加載定義好的公共的js或者css
{% extends 'base.html' %}
{% block extJS %}
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
{% endblock %}
12.3 定義首頁index.html
在首頁index.html中,我們在{% block extJS %}中使用{{ block.super }}去加載之前在base_main.html中定義好了的js文件,將它繼承過來,那么在index.html中就會加載兩個js文件了。實現(xiàn)了將公共的js文件或者css文件單獨提煉出去,不需要再每個頁面中重復的去寫加載js的重復代碼了。
{% extends 'base_main.html' %}
{% block title %}
首頁{{ user.username }}
{% endblock %}
{% block extCSS %}
<link rel="stylesheet" type="text/css" href="/static/css/public.css" />
{% endblock %}
{% block extJS %}
{{ block.super }}
<script type="text/javascript" src="/static/js/public.js"></script>
{% endblock %}
{% block indexbody %}
<frameset rows="100,*" cols="*" scrolling="No" framespacing="0"
frameborder="no" border="0">
<frame src="{% url 'app:head' %}" name="headmenu" id="mainFrame" title="mainFrame"><!-- 引用頭部 -->
<!-- 引用左邊和主體部分 -->
<frameset rows="100*" cols="220,*" scrolling="No"
framespacing="0" frameborder="no" border="0">
<frame src="{% url 'app:left' %}" name="leftmenu" id="mainFrame" title="mainFrame">
<frame src="{% url 'app:grade' %}" name="main" scrolling="yes" noresize="noresize"
id="rightFrame" title="rightFrame">
</frameset>
</frameset>
{% endblock %}
