一、Python用具 - pip
一、做用:
Python的軟件包管理器,有一些python包被集成到了pip中。只要被集成到pip中的包,都容許經過pip直接安裝
二、安裝 pip
sudo apt install python-pip(python2)
sudo apt install python3-pip(python3)
三、使用pip/ pip3
一、安裝/下載/更新/刪除 python包
一、安裝python包(下載並安裝)
sudo pip3 install SomePackage
sudo pip3 install PyMySQL==0.7.11(若是不寫版本號默認爲最新的版本)
二、下載python包(值下載不安裝)
sudo pip3 download SomePackage
三、刪除python包
sudo pip3 uninstall SomePackage
四、更新(升級)python包
sudo pip3 upgrade SomePackage
二、查看當前環境中所安裝的包
pip3 list
三、搜索
pip3 search SomePackage
四、展現
pip3 show SomePackage
五、記錄現有環境的python包
一、pip3 freeze > requirements.txt
將當前python環境中所安裝的內容打包成一個txt文件
二、pip3 install -r requirements.txt
容許在當前系統下,逐一安裝requirements.txt中全部列出的內容
二、Python工具 - VirtualEnv
一、什麼是VirtualEnv - 虛擬環境
virtualEnv是python中的虛擬環境,在作python應用開發時,若是不想在大的python環境中安裝各類各樣的包的話,則能夠虛擬出一個python環境,可讓虛擬環境專門爲某一應用而存在。容許在虛擬環境中安裝各類包且不影響大的python環境
二、安裝VirtualEnv
sudo pip3 install virtualenv
三、建立 和 使用 虛擬環境
一、準備工做
mkdir my_env
cd my_env
二、建立虛擬環境
virtualenv 虛擬環境名稱
示例:virtualenv default
建立指定版本的虛擬環境
virtualenv -p /usr/bin.python2.7 名稱
virtualenv -p /usr/bin.python3.6 名稱
三、啓動虛擬環境
注意:不能在bin目錄中啓動虛擬環境(根目錄下的bin目錄)
source bin/activate
四、退出虛擬環境
deactivate
五、刪除虛擬環境
rm 虛擬環境目錄 -rf
注意:在虛擬環境中使用pip安裝和卸載內容時,不要使用sudo進行受權,若是使用則操做的是大環境
四、虛擬環境管理工具 - VirtualenvWrapper
一、做用
第三方的管理工具,可以快速,高效且方便的管理虛擬環境
二、安裝虛擬環境管理工具
sudo pip3 install virtualenvwrapper
三、配置virtualenvwrapper
在~(家目錄)目錄下,有一個終端管理文件 .bashrc(在~目錄下,輸入ll查看)
配置.bashhrc,以便在啓動終端時,就自動啓動虛擬環境管理工具
修改.bashrc: sudo vi .bashrc
在.bashrc 最底部增長一下內容
一、export WORKON_HOME=~/my_env:
將~/my_env 做爲虛擬環境的管理目錄,全部使用virtualenvwrapper建立的虛擬環境都默認保存於此
二、若是系統中包含多個python執行環境的話,則添加一下內容
export VIRTUALENVWRPPER_PYTHON=/usr/bin/python3
三、source /usr/local/bin/virtualenvwrapper.sh:默認啓動刮管理工具
四、在~目錄下,執行一遍.bashrc
source .bashrc
四、使用虛擬環境管理工具
一、建立並進入虛擬環境管理工具
一、mkvirtualenv 虛擬環境名稱
二、mkvirtualenv --python=/usr/bin/python2.7 env2.7
二、查看當前所維護的全部虛擬環境
workon
三、切換虛擬環境
workon 虛擬環境名稱
四、退出虛擬環境
deactivate
五、刪除虛擬環境
rmvirtualenv 虛擬環境名稱
三、WEB 與 服務器
一、WEB:表示用戶能夠瀏覽的網頁(HTML,CSS,JS)
二、服務器:專門給用戶提供服務的一臺機器
一、硬件 與 軟件
硬件範疇:一臺主機
軟件範疇:一個可以接收用戶請求並給出響應的程序javascript
一、APACHEphp
二、TOMCATcss
三、IIS(Internet Information Service)html
四、Nginx前端
二、做用:
一、存儲WEB上的信息(網頁,圖片,音視頻,css,js)
二、可以處理用戶的請求(request)並給出響應(response)
三、可以執行服務器端程序:如查詢數據庫
三、WEB與服務器的關係java
WEB須要放在服務器上纔可以被用戶訪問python
運行在服務器端的程序,能夠由不一樣的語言來編寫
Java語言-->JSP
C#語言-->ASP>NET
PHP語言-->php
Python語言-->Django
四、網站請求的全過程
一、用戶:輸入域名,經過域名解析(DNS)器獲得IP地址
二、向服務器發送http(開80端口)/https(開440端口)請求
三、傳輸層TCP協議,通過網絡傳輸和路由解析
四、WEB服務器接收HTTP請求
五、服務器處理請求內容,並進行必要的數據交換(咱們須要作的事情)
六、將響應的內容發回給瀏覽器(響應)
七、瀏覽器解析HTML
八、顯示解析好的內容
四、框架
一、什麼是框架
框架是一個爲了解決某些開放性問題而存在的一種結構。框架自己提供了最基本的功能,咱們只需在這些基本功能上構建本身的操做便可。
二、框架的優勢
一、快速開發 - 基本功能已經提供好了
二、能夠解決大部分問題
三、bug少,穩定性較高
三、框架的分類
一、前端框架
處理前端內容(HTML,CSS,JS)
二、後端框架
處理服務器程序的
Spring -Java
三、全棧框架
包含WEB總體的解決方案,包括開發框架,運行環境
Rails(Ruby)
Django(Python)
四、Python的WEB框架
一、Django:重量級的Python Web框架
二、Tornado:異步框架
三、Flask:輕量級框架,直接引入模塊便可使用
四、Webpy:輕量級框架
五、Web2py:全棧框架,webpy的增強版
一、設計模式 與 框架模式
一、設計模式
設計模式,是一套被反覆使用,多數人知曉並通過分類的代碼設計經驗的總結,是爲了解決一些通用性問題的
目的:重用代碼並保證代碼的可靠性
官方認證的設計模式有23中:單列模式,抽象工廠模式,觀察者模式等 《大話設計模式》
二、框架模式
代碼的重用,框架模式是解決如何設計程序框架的代碼,在框架模式中會包含多種的設計模式
如:MVC,MTV,MVVM,ORM,...
一、MVC
M:Models,模型層,
在程序中主要處理數據,負責在數據庫中對數據進行存取操做(CRUD)
V:Views,視圖層
應用程序中處理顯示的部份內容(HTMl,JSP)
C:Controllers,控制器層
處理用戶交互的部分,一般負責從模型中取出數據,再進行業務的處理,最後將數據給視圖,並將視圖給客戶端mysql
二、MTV
M:Models 模型層,jquery
模型層,負責數據庫建模以及CRUD的操做
T:Templates 模板層
用於處理用戶顯示的部份內容,如:html
V:Views 視圖層
處理用戶交互部分,從模型中獲取數據,再將數據給模板,在顯示給用戶git
二、Django框架
一、什麼是Django
是一個開源框架,2005年發佈,採用python語言開發的。早期Django是作新聞和內容管理的網站的,提供了很是強大的後臺管理系統,採用的是MTV框架模式
二、Gjango的優缺點
一、優勢
一、開源框架,有完美的文檔支持
二、解決方案比較完整,內部功能也比較多
三、提供完整的路由系統,優雅的URL解析方式
四、自助式的後臺管理
二、缺點
一、耦合度偏高
三、Django的安裝
一、Linux中的安裝
一、查看已安裝的Django
一、進入到虛擬環境中
二、進入到python的交互模式中
三、在交互模式中輸入
一、import django
二、django.VERSION
二、在線安裝 - 使用 pip
一、終端中輸入
pip install django(安裝django的最高版本)
pip install django==1.11.8
注意:在虛擬環境中不要使用sudo
二、離線安裝
一、下載所須要的django包
二、在Linux中解壓django
tar - xvf Gjango-1.11.8.tar.gz
三、進入到Django文件夾中
四、安裝
python setup.py install
二、Windows中的安裝
一、在線安裝
控制檯: pip3 install django==1.11.8
二、離線安裝
一、下載django安裝包
二、解壓django包
三、進入到django包中
python setup.py install
四、使用Django
一、建立Django項目
直接使用django-admin去建立Django項目
一、找到項目文件夾(自定義)
二、使用django-admin 指令
django-admin startproject 項目名稱
二、啓動Django項目
一、進入到項目文件夾中
二、經過manage.py 啓動項目
一、
python manage.py runserver
或 ./manage.py runserver
只能在本機訪問
http://localhost:8000
http://127.0.0.1:8000
二、
python manage.py runserver 0.0.0.0:8000
或 ./manage.py runserver 0.0.0.0:8000
容許在局域網內訪問。能夠經過IP地址訪問,可是須要將setting.py文件中ALLOWED_HOSTS = []修改成ALLOWED_HOSTS = ["*"]
五、Django結構介紹
一、manage.py
負責執行django中的各項操做的文件,又叫命令腳本文件
如:
一、啓動服務
二、建立應用
三、建立管理員、用戶
....
二、主文件夾(名稱與項目名稱相同)
存放項目的最基礎的配置文件
一、__init__.py
項目初始化文件,每當服務器啓動的時候,會自動執行,若是有自定義的初始化操做,須要放在該文件中
二、urls.py
項目的基礎url(路由)配置文件
路由:去哪裏找執行的程序
三、wsgi.py
配置應用服務器的文件,暫時不用
四、settings.py(重要)
項目的主設置文件:應用:模板,數據庫,語言,時區....
一、BASE_DIR:項目的絕對路徑
二、DEBUG:調試模式
開發過程當中,推薦使用Ture,上線運行時,必須改成False
三、ALLOWED_HOSTS
設置容許訪問本地項目的地址列表,若是不設置的話,只能本機訪問,推薦用"*",表示任何機器都容許訪問當前項目
四、INSTALLED_APPS
指定已經安裝的應用,若是有自定義應用的話,須要在此註冊
五、MIDDLEWARE:註冊中間件
六、ROOT_URLCONF:指定項目的基礎路由配置文件
七、TEMPLATES:指定模板的信息
八、DATABASES:指定數據庫的信息
九、LANGUAGE_CODE:指定語言,容許修改成zh-Hans
十、TIME_ZONE = 'UTC':指定時區,建議改成Asia/Shanghai
六、settings的加載流程
一、先加載globals_settings.py
位於:/home/xdl/my_env/env3.5/lib/python3.6/site-packages/django/conf/globals_settings.py
二、再加載項目中的settings.py
注意:若是globals_settings中的內容與項目settings中的內容衝突的話,優先使用項目中的settings中的內容
七、初始 django-admin 和 mangage.py
一、在終端輸入django-admin命令
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
runserver
sendtestemail
shell:python3 manage.py shell ,進入django的交互環境,
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject#建立項目
test
testserver
二、進入項目主目錄文件夾,輸入./manage.py
[auth]
changepassword #修改密碼
createsuperuser #建立超級用戶
示例:
一、首先須要建立一張用於存儲用戶信息:./manage.py migrate
二、建立用戶:./manage.py createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell #進入到Django數據shell交互模式
diffsettings
dumpdata
flush
inspectdb #將數據表直接導出爲Models
loaddata
makemessages
makemigrations#建立數據庫日誌文件,記錄Models的改動
migrate #將數據庫日誌文件同步到數據庫中
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp #建立應用
startproject
test
testserver
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver #啓動服務
八、URL的使用
一、urls.py
默認在主文件夾中,包含全部的地址映射。
每當一個請求產生後,都會到urls.py中進行地址的匹配,匹配上後再找對應的處理程序(View視圖)去處理
二、測試
一、在主文件夾中,建立views.py
做用:包含全部定義好的視圖(處理程序)
內容包括:
from django.http import HttpResponse
def fun_views(request):
'''視圖,處理用戶的請求並給出響應
request:表示用戶的請求信息
HttpResponse:響應給客戶端的內容'''
return HttpResponse("Hello django")
二、在urls.py中追加
from .views import *
urlpatterns = [
url(r'^admin/',admin.site.urls),
//若是訪問路徑是fun/ 的話,則交給fun_views視圖處理函數去處理
url(r'^fun/$',fun_views),//若是這裏添加了自定義視圖處理函數時,localhost:8000將會失效
//若是請求的URL在這裏能夠匹配多個,則只能執行第一個匹配到的
]
三、url函數
url函數的語法:
url(regex,views,kwargs=None,name=None)
一、regex:正則表達式,匹配請求的url
二、views:url處理的視圖函數,一般都是自定義的
三、kwargs:字典,用來向views傳參
四、name:字符串,給url()起一個別名,主要在模板中匹配{%url%}一塊兒使用
四、url向view傳參
一、使用正則表達式傳參
使用正則表達式的子組傳參,使用()
urlpatterns=[
//訪問路徑必須是fun
url(r'^fun/$',fun_views),
//訪問路徑必須是fun
url(r'^fun/$',fun_views),
url(r'^fun/(\d+)',fun_arg1_views),
]
注意
一、在url()中,一個子組()表示一個參數
二、在views.py中,對應的處理函數要根據url()中子組的個數,相應的定義參數,定義的參數要位於request以後
練習:
一、訪問地址:localhost:8000/18/0223/15,如何獲取18 0223 15
def fun_arg3_views(request,num1,num2,num3):
return HttpResponse("%s %s %s"%(num1,num2,num3));
url(r'^(\d{2})/(\d{4})/(\d{2})$',fun_arg3_views),
二、使用url()第三個參數,字典傳參
urlpatterns=[
url(r'^showname/$',show_views,{'name':"zhang",'age':25}),
]
views.py:
def show_views(request,name,age):
return HttpResponse(name+':'+str(age))
注意:
一、視圖處理函數中,必須聲明參數
二、參數的名稱 和 位置 必需要與字典中的名稱和位置保持一致
三、Django中的應用
一、什麼是應用
應用是網站中的一個獨立的模塊,包含獨立的顯示信息
在項目主文件夾中通常不處理其餘的請求,主要就作初始化設置 以及 地址的分發
實際操做中,會將請求交給不一樣的應用去處理
二、建立應用
一、命令: ./manage.py startapp 應用名稱
二、在settings.py中註冊應用:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]
三、應用的結構組成
一、migrations 目錄
存放數據庫日誌文件,是一個django與數據庫交互的中間文件
二、__init__.py
應用的初始化操做文件
三、admin.py
應用的後臺管理配置文件
四、apps.py
應用的屬性設置文件,不需改動
五、modles.py
Modles模型文件
六、tests.py
測試模塊,一般不用
七、views.py
定義視圖的py文件
練習:
建立應用,並進行註冊
在day02_exer 中建立應用
一、index - 主頁面的應用
./manage.py startapp index
二、news - 新聞的應用
./manage.py startapp news
三、sports - 體育的應用
./manage.py startapp sports
四、musics - 音樂的應用
./manage.py startapp musics
在settings.py中的INSTALLED_APPS列表中添加以上應用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
'news',
'sports',
'musics',
]
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ] urlpatterns += [ url(r'^music/', include('music.urls')), url(r'^sport/',include('sport.urls')), url(r'^news/',include('news.urls')), #匹配空的時候必定要放在最後 url(r'^', include('index.urls')), ]
一、Django模板(Template)
一、什麼是模板
就是一個網頁,能夠被view響應給用戶
目的是爲了解決複雜的顯示問題
二、模板的設置
一、BACKEND:指定模板的搜索引擎,不用改動(就是指定到哪裏搜索模板)
二、DIRS:指定模板所存放的目錄,若是DIRS爲空的話而且APP_DIRS爲True,那麼django會自動搜索每一個應用中的templates文件做爲模板管理目錄
DIRS = ['index.trmp','music.temp']
推薦:
一、DIRS保持爲空
二、在每一個應用中,建立一個templates的文件夾
三、APP_DIRS:值爲boolean類型
True:首先從DIRS中指定的文件夾中查找模板,若是沒有找到指定模板的話,則再搜索templates目錄
三、模板的加載方式
一、使用loader 獲取模板,經過HttpResponse進行響應
from django.template import loader
def xxx(request):
#一、經過loader加載模板
t = loader.get_template('show.html')
#二、將模板渲染成字符串
html = t.render({})
#三、經過HttpResponse響應回去
return HttpResponse(html)
說明:
render({}),字典中的是數據,會傳入html文檔中,在HTML中經過{{字典的鍵}}取值,{{num1}}
render({}),字典參數,能夠經過locals(),獲取該函數中的局部變量的字典,進行傳遞
二、使用render直接加載
return render(request,'模板名稱',{})
四、url()的name參數
urlpatterns = [
url(regex,views,kwargs=None,name=None)
]
name:定義當前url的別名,容許在Template中使用該別名來找到對應的url(反向解析)
反向解析:經過name 的值來匹配出對應的regex路徑
在Django模板中使用name實現鏈接
{% url 'name值' %}
若是url中有參數須要{% url 'name值' 參數1 參數2 ...%}
在視圖中實現name別名反向解析出對應的URL地址
須要引包:from django.shortcuts import reverse
語法:
一、無參數解析:reverse("別名")
二、帶參數解析:reverse("別名",args = (參數1,參數2....))
from django.shortcuts import render from django.http import HttpResponse from django.urls import reverse # Create your views here. def index_views(request): return HttpResponse("news index_views") def reverse_views(rquest): #反向解析url(不帶參數),/news/reverse #url = reverse("reverse") #反向解析url(帶參數),/news/reverse/2018/08 url = reverse('reverse_args',args=(2018,'08')) return HttpResponse("反向解析出的URL:"+url)
五、模板的語法
一、變量
一、 做用:容許將後端的數據傳遞給模板(html),在模板中,會根據變量的實際值進行顯示
二、在Django中容許傳遞給模板做爲變量的數據類型
數字,字符串,列表,元組,字典,函數,對象,類。 集合不能夠
三、變量語法
變量們必需要封裝到字典中才能傳遞給模板
一、使用render加載模板
dic = {
’變量1’:‘值1’,
‘變量2’:‘值2’,
....
}
return render(request,'xx/html',dic)
二、使用loader加載模板
dic = {
’變量1’:‘值1’,
‘變量2’:‘值2’,
....
}
t = loader.get_template('x.html')
#渲染成字符串是須要傳遞變量字典到模板中
html = t.render(dic)
return HttpResponse(html)
四、在模板中使用變量:
{{變量名}}
若是要取列表,字典,元組中的值要經過變量名.下標 或 變量名.鍵
def var_views(request): #聲明變量字典 l = ['金毛獅王','白眉鷹王','青'] t = ('潘林連','西門慶','武大郎') dic = { 'SHZ':"水滸傳", 'xyj':"西遊記", 'hlm':'紅樓夢' } def fun(): return '函數' class Dog(object): name = '阿拉斯基' def eat(self): return '吃狗糧' vars = { 'num':15, 'str':'模板中的字符串變量', 'tup':t, 'list':l, 'dic':dic, 'fun':fun(),#等價於'fun':fun 'dog':Dog(),#等價於Dog } return render(request,'02_var.html',vars)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>num:{{ num }}</h3> <h3>str:{{ str }}</h3> <h3>tup:{{ tup }}</h3> <h3>tup[0]:{{ tup.10 }}</h3> <h3>list:{{ list }}</h3> <h3>list[1]:{{ list.1 }}</h3> <h3>dic:{{ dic }}</h3> <h3>dic['xyj']:{{ dic.xyj }}</h3> <h3>fun:{{ fun }}</h3> <h3>dog:{{ dog }}</h3> <h3>dog.name:{{ dog.name }}</h3> <!--調用類方法內中函數時只用對象.函數名,無需家括號--> <h3>dog.eat:{{ dog.eat }}</h3> *********************************************************** <h3>tup:{{ t }}</h3> <h3>tup[0]:{{ t.1 }}</h3> <h3>list:{{ l }}</h3> <h3>list[1]:{{ l.1 }}</h3> <h3>dic:{{ dic }}</h3> <h3>dic['xyj']:{{ dic.xyj }}</h3> <h3>fun:{{ fun }}</h3> <h3>dog:{{ Dog }}</h3> <h3>dog.name:{{ Dog.name }}</h3> <!--調用類方法內中函數時只用對象.函數名,無需加括號--> <h3>dog.eat:{{ Dog.eat }}</h3> </body> </html>
二、標籤
一、什麼是標籤
容許嵌套一些服務器端的邏輯運算到模板中
二、語法
{% %}
三、經常使用標籤
一、{% if 條件 %} ...{% endif %}
接受:not and or
可是 :and 和 or 不能同時出現
如下內容當成False處理:
空[]
空()
空{}
數字:0
空字符串
特殊對象:None
二、{%if 條件 %}...{%else%}...{%endif%}
三、
{%ifequal 值1 值2%}...{%endifequal%}:判斷值1與值2是否相等
{%ifequal 值1 值2%}...{%else%}...{%endifequal%}
四、{% for 變量 in 列表|元組|字典%}{%endfor%}
容許使用的內置變量(免聲明)
forloop
一、forloop.counter:記錄循環的次數
二、forloop.counter0:同上,但從0開始
三、forloop.revcounter:記錄未被遍歷的數量
四、forloop.revcounter0:同上,從0開始
五、forloop.first:布爾值,標記是否爲第一個項目
六、forloop.last:布爾值,表示是否爲最後一個項目
{% for str in l %} <!--將第一條數據的背景色變爲紅色--> <h3 {% if forloop.first %} style="background:red;" {% endif %} >數據{{forloop.counter0}}:{{ str }} </h3> {% endfor %}
五、{%url%}
六、{%static%}
七、{%extends%}:用做模板繼承
八、comment 標籤
做用:在服務器端就被註釋的內容,不會被渲染到客戶端的
<!--註釋內容-->>:客戶端註釋會被渲染到客戶端,在其中的{{ 服務器代碼}},回去執行解釋
三、過濾器
一、做用
在顯示變量以前,容許對數據進行篩選或改變
二、過濾器的語法
{{var|過濾器}}
三、經常使用過濾器
一、{{var|upper}}:將var的數據變爲大寫
二、{{var|lower}}:將var的數據變爲小寫
三、{{var|add}}:
四、{{var|floatformat:n}}:將var四捨五入到n爲小數
五、{{value|truncatechars:n}}:將value截取保留至n位字符(包含三個點...)
自定義標籤和過濾器
步驟:
一、在應用目錄下建立templatetags目錄
二、在templatetags建立模塊文件,並導入Django內部方法
三、在模板最上方中加載自定義的模塊文件,{% load 模塊文件名%}
自定義過濾器
一、在templatetags目錄下建立python模塊,例如命名爲tags.py
from django import template register = template.Library() @register.filter def value_verification(value): # value爲前端傳遞的參數
'''最多傳遞兩個參數''' try: int(value) return True except: return False
<!--前端模塊中的代碼-->
{% load app01_func %} {% if load|value_verification %} {{ num }} is a valid int number. {% else %} {{ num }} is letter. {% endif %}
自定義標籤
一、simple_tag的代碼方式與filter同樣,不一樣的是在裝飾器部分和前端調用的方式不一樣
from django import template register = template.Library() @register.simple_tag def value_verification(value): # value爲前端傳遞的參數 '''能夠傳遞多個參數''' try: int(value) return True except: return False
二、前端模塊中調用{% value_verification num %}
filter 和 simple_tag的區別
一、filter能夠用在if 條件判斷中,可是最多隻能有兩個參數,能夠將多個參數用特定字符拼接成一個字符串傳遞給後端,後端經過拆分獲取多個參數
二、simple_tag不能用在if、for語句中,能夠傳遞多個參數
三、模板中的調用方式不一樣
一、filter將咱們指定的函數變成了返回值可執行的方法{{ 參數1 | value_verification:參數2 }},冒號後面不能有空格
二、simple_tag將函數功能變爲標籤功能{% value_verification 參數1 參數2...... as 返回結果的別名 %}
四、靜態文件的處理
一、什麼是靜態文件
在Django中,不被解釋器動態解析的文件就稱爲靜態文件,在Django中,物理路徑(磁盤中真是存在的)是沒法找到靜態文件的
模板中所用到的css,js,image等一些資源文件都是靜態文件
二、Gjango中靜態文件的處理
須要在settings.py中設置靜態文件的訪問路徑 和 存儲路徑
一、STATIC_URL:設置靜態文件的訪問路徑
STATIC_URL = '/static/'
二、STATICFILES_DIRS:設置靜態文件的存儲路徑
一、STATICFILES_DIRS = (BASE_DIR,'static')
二、STATICFILES_DIRS = (os.path.join(BASE_DIR,'靜態文件目錄名'))
靜態文件目錄存放位置:
一、全部應用中建立一個同名目錄
二、項目的根目錄處也能夠建立一個同名文件
三、訪問靜態資源
一、<img src="/static/images/huiyuan.jpg">
二、使用{%static%}訪問靜態資源
{%static%}:表示的就是靜態文件資源的訪問路徑(就是setting.py中STATIC_URL的值,STATIC_URL = '/static/')
一、模板的最頂層增長{%load static%}
二、使用靜態資源文件時
<img src="{%static 'images/huiyuan.jpg'%}"
五、模板的繼承
一、什麼是模板的繼承
當多個模板(網頁)具有大部分相同的內容時,就可使用繼承的方式,將相同的內容繼承過來,在增長/修改屬於本身的內容便可
二、模板繼承的語法
一、在父模板中增長{%block 名稱%}...{%endblock%}
說明:名稱不能重複
二、在子模板中
一、在最頂層第一句話增長:
{%extends '父模板的名稱'%}
二、增長block標記,編寫屬於本身的內容
{%block 名稱%}//這裏的名稱要與父模板{%block 名稱%}中的名稱相同
屬於子模板中本身的內容
//一旦引用次標記,則此處再也不顯示父模塊中的內容
{%endblock%}
二、Django模型(Model)
一、什麼是模型
模型,就是根據數據中數據表的結構而建立出來的class。
數據庫中的每一張表到編程語言中就是一個class
數據庫表中的每個字段(列)能夠被構建成class中的一個成員變量(屬性),而且在模型中,完成對數據庫的CRUD操做
C:Create
R:Retrieve(檢索查找)
U:Update
D:Delete
二、建立 和 使用模型 - ORM
一、什麼是ORM
ORM:Object Relational Mapping(對象關係映射)
簡稱:ORM, O/RM, O/R Mapping
三大特徵:
一、數據表到類(class)的映射
容許將表自動生成一個類,也容許將一個類自動生成一張表
二、數據類型的映射
容許將表中字段的類型自動生成到編程語言中對應的數據類型,也容許將編程語言中的數據類型生成數據表中對應的字段類型
三、關係映射
數據庫中表的關聯關係:
一對一,一對多(多對一),多對多
將表中的關聯關係也映射到編程語言的class中,經過建立對象的關係來完成映射
容許將類與類之間的關係自動映射成表與表之間的關係
class A(object):
name = None
class B(object):
a = A()#在表中經過外鍵進行關聯
二、ORM的優勢
一、提升了開發效率,可以自動完成實體類到數據表的映射,
二、能夠省略龐大的數據訪問層,即使不用SQL編碼(語句),就可以完成對數據的CRUD操做
三、建立 和 配置數據庫
一、建立數據庫(支持中文)
create database webdb default charset=utf8
create database webdb default charset utf8 collate utf8_general_ci
二、Django中數據庫的配置
settings.py中配置數據庫信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'webdb',
'USER': 'debian-sys-maint',
'PASSWORD':'Lo0r79JmxvMFNtA2',
'HOST':'localhost',
'PORT':'3306',
}
}
一、ENGINE:引擎
django.db.backends.mysql
二、NAME:要鏈接到的數據庫名稱
三、USER:用戶名稱
四、PASSWORD:密碼
五、HOST:鏈接的主機,本機的話localhost/127.0.0.1/不寫
六、PORT:端口,3306
四、安裝pymysql
注意:Django中要鏈接MySQL數據庫的話要依賴於MySQLdb,經過pymysql解決問題
pip install pymysql==0.7.11
五、在主文件夾找找到__init__.py寫入
import pymysql
pymysql.install_as_MySQLdb()#轉換爲MySQLdb
六、啓動django
./manage.py runserver
四、數據庫的同步操做
一、./manage.py makemigrations
做用:將每一個應用下的models.py文件生成一個數據庫的中間文件(映射成一個數據庫日誌文件),並存放在migrations目錄中
二、./manage.py migrate
做用:將每一個應用下的migrations目錄中的中間文件(日誌文件)同步到數據庫中
當migrations目錄中沒有中間文件時,會建立Django中自帶的數據表
五、編寫Models(重難點)
一、注意:
一、Models中的每一個class都稱之爲 模型類(Model)或實體類(Entry)
實體:數據表中的一行記錄,就是一個實體
實體完整性:確保每張表中的數據不能有重複的,數據表中的主鍵,是實現實體完整型的方式之一
二、Models中的每一個實體類,必須繼承自models.Model
二、示例:
在models.py中
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=20)
website = models.URLField()
from django.db import models import datetime # Create your models here. #實體類:Publisher #對應到數據庫中的一張,表表名爲index_publisher(應用名_實體類名小寫) #該類中的每一個屬性,會對應到數據表中的每一個字段啊 class Publisher(models.Model): name = models.CharField(max_length=30,deafult='匿名') address = models.CharField(max_length=60) city = models.CharField(max_length=30) country = models.CharField(max_length=30) website = models.URLField() class Author(models.Model): name = models.CharField(max_length=30) age = models.IntegerField() email = models.EmailField(null=True) class Book(models.Model): title = models.CharField(max_length=50) publication_date = models.DateField(default=datetime.datetime.now())
六、Django中的字段類型以及字段選項
一、字段類型(Field Types):映射到數據庫表中的數據類型
一、BooleanField():tinyint()
二、CharField():varchar()
三、DateField():date
四、DateTimeField():datetime(6),6位精度 2018-08-27 16:43:20.000000
五、FloatField():double()
六、FileField():varchar(100)
七、EmailField():varchar(254)
八、IntegerField():int(11)
九、ImageField(upload_to=None):varchar(100)存放文件路徑
uimg=models.ImageField(upload_to='images/users/')
十、URLField():varchar(200)
十一、DecimalField(max_digits=7,decimal_places=2):decimal(7,2),一般用來表示錢
十二、TextField():longtext()存放大量數據
二、字段選項:對生成的字段的說明信息
一、null:是否容許爲空,默認爲False
name = models.CharField(max_length=30,null=True)
二、default:爲該字段設置默認值
name = models.CharField(max_length==30,default="匿名")
三、db_cloumn
指定當前屬性(字段)對應到數據庫表的列名,若是不指定則採用屬性名做爲列名
三、說明:
若是在原先實體類中添加屬性(字段)時,必須給這個字段設置爲容許爲空(null=True)或者給一個默認值default=‘值’,不然會有以下提示
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
七、數據的導入和導出(數據遷移)以及版本切換
一、版本切換
./manage.py migrate 應用名稱 版本號
./mansge.py migrete index 0001 //會將原先已經映射的數據表刪除
二、數據庫的導出
一、mysqldump -u... -p 數據庫名 >文件.sql
導出全部的表結構以及數據
二、mysqldump -u... -p -d 數據庫名 >文件.sql
只導出全部的結構
三、數據庫的導入
mysql -u.. -p 數據庫名 < 文件.sql
四、經過數據庫自動導出Models
./manage.py inspectdb >文件名.py
表名index_book變爲實體類名爲IndexBook
class IndexBook(models.Model):
title = models.CharField(max_length=50)
publication_date = models.DateField()
class Meta:
managed = False
db_table = 'index_book'
一、模型的數據庫操做方法(CRUD)
一、經過視圖向DB中增長數據
一、Entry.objects.create(屬性=值,屬性=值)
返回值:建立好的實體,
Author.objects.create(name='王寶強',age=33,email='wangbaoqiang@green.com')
二、建立一個實體對象,並經過save()方法完成增長
obj = Entry(屬性=值,屬性=值)
obj.save()
三、經過字典建立實體對象,在調用save()
dic = {
"name":"xx",
"age": ,
"email":"xx"
}
obj = Author(**dic)
obj.save()
示例:
dic = {"name":"陳羽凡","age":38,"email":"chenyufan@green.com"}
obj = Author(**dic)
obj.save()
def add_views(request): #方法一、向Author實體中增長一條記錄 ret = Author.objects.create(name='老舍',age=85,email='laoshe@163.com') return HttpResponse(ret)#返回一個實體類對象,age是str,int均可以 #方法二 author = Author(name='巴金',age=75,email='bajin@163.com') ret = author.save() return HttpResponse(ret)#返回值爲None #方法三 dict = { 'name':'冰心', 'age':80, 'email':'bingxin@163.com', } author = Author(**dict) ret = author.save() return HttpResponse(ret)#返回None
二、查詢操做(重難點)
全部的查詢都要在Entry.objects.基礎上完成
一、基本查詢操做
語法:all()
用法:Entry.objecsts.all()
返回:QuerySet(查詢結果集,是一個封裝了若干對象的列表)
<QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>
<QuerySet [<Author: 老舍>, <Author: 老舍>, <Author: 巴金>, <Author: 冰心>]>
def query_views(request): #查詢Author實體中全部的數據 #返回一個列表,其中封裝了若干的對象 authors = Author.objects.all() for au in authors: print(au.name,au.age,au.email) return HttpResponse('query ok')
二、查詢接口
一、all()
Entry.objects.all()
至關於:select * from ...
二、查詢指定列的操做
語法:values("列名1",‘列名2’...)
Entry.objects.values('name')
至關於:select name from ...
做用:查詢全部記錄的某一列的值
返回值:QuerySet(查詢結果集,是一個封裝了若干字典的列表)<QuerySet [{'name': '王寶強'}, {'name': '賈乃亮'}, {'name': '陳羽凡'}]>
注意:values()能夠用在QuerySet(查詢結果集)後面好比:all().values()
def query_views(request): #查詢Author實體中name 和 age的信息 authors = Author.objects.values('name','age') print(authors) # < QuerySet[ # {'age': 85, 'name': '老舍'}, # {'age': 85, 'name': '老舍'}, # {'age': 75, 'name': '巴金'}, # {'age': 80, 'name': '冰心'}] > for au in authors: print(au['name'],au['age']) # 老舍 85 # 老舍 85 # 巴金 75 # 冰心 80 return HttpResponse('ok')
三、values_list('列1',‘列2’)
Entry.objects.values_list("name","age")
至關於:select name,age from...
返回值:QuerySet,是一個有若干元祖所組成的列表:<QuerySet [('王寶強', 33), ('賈乃亮', 35), ('陳羽凡', 38)]>
注意:values_list()能夠用在QuerySet(查詢結果集)後面好比:all().values_list()
def query_views(request): #查詢Author實體中name 和 age的信息 authors = Author.objects.values_list('name','age') print(authors) #< QuerySet[ # ('老舍', 85), # ('老舍', 85), # ('巴金', 75), # ('冰心', 80)] > for au in authors: print(au[0],au[1]) # 老舍 85 # 老舍 85 # 巴金 75 # 冰心 80 return HttpResponse('ok')
四、get()
只查找一條記錄是使用,也只能返回一條記錄,若是查詢返回多條記錄的話,則報錯
Entry.objects.get(id=1)
至關於:select * from .... where id=1
返回值:Author object
注意:查詢多於一條記錄或者沒有查詢到結果都會拋出異常
一、get() returned more than one Author -- it returned 2!(Exception Type: MultipleObjectsReturned)
二、Author matching query does not exist(Exception Type: DoesNotExist)
五、exclude()
做用:對給定條件取反
Entry.objects.exclude(id=1)
至關於:select * from ...where not id=1
返回值:<QuerySet [<Author: Author object>, <Author: Author object>]>
Entry.objects.exclude(id=1,age=33)
至關於:slect * from ...where not(id=1 and age=3)
六、order_by()
Entry.objects.order_by('列名1',‘列名2’...)
指定按照字段進行排序,若是是多個字段,中間用,逗號隔開。默認是按照升序排列,須要降序的話,只需在列名前加」-「符號便可
返回值:QuerySet(查詢結果集,是一個封裝了若干對象的列表)<QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>
def query_views(request): #查詢Author實體中的數據按照年齡升序排列 authors = Author.objects.order_by('age') print(authors) #< QuerySet[ # < Author: 巴金 >, # < Author: 冰心 >, # < Author: 老舍 >, # < Author: 老舍 >] > for au in authors: print(au.name,au.age) #巴金 75 #冰心 80 #老舍 85 #老舍 85 return HttpResponse('ok')
七、filter()
根據自定義條件查詢結果集,能夠是一個,也能夠是多個,多個的話,條件用,逗號隔開。
若是是多個條件的話,其內部是使用AND來進行條件鏈接的
返回值:QuerySet(查詢結果集,是一個封裝了若干對象的列表)
一、使用Entry的屬性來做爲filter()的條件
示例:
一、Author.objects.filter(id=1)
至關於:select * from author where id=1
二、Author.object.filter(id=1,age=33)
至關於:select * from author where id=1 and age=3
二、使用Field Lookups(查詢謂詞),完成複雜條件查詢
查詢謂詞:每個獨立的查詢謂詞就是一個獨立的查詢條件,全部支持使用查詢條件的位置處,都容許適應查詢謂詞,get(),filter(),exclude()
語法:屬性__查詢謂詞=,雙下劃線
一、__exact
做用:等值判斷
Author.objects.filter(id__exact=1)
select * from author where id=1
查看文檔:https://docs.djangoproject.com/en/2.1/ref/models/querysets/
def query_views(request): #查詢Author實體中郵箱屬性包含字符a authors = Author.objects.filter(email__contains='a') return render(request,'query.html',locals())
二、子查詢
inner = Author.objects.filter(name__exact="王寶強").values("age")
authors = Author.objects.filter(age__gt=inner)等價於authors = Author.objects.filter(age__gt=inner[0]['age'])
三、修改操做
一、修改單個對象
一、經過get()獲取要修改的實體對象
二、經過實體對象修改屬性值
三、在經過實體對象的save()函數,實現保存
auth = Author.objects.get(id=1)
auth.name='寶強.王'
auth.age = 45
auth.save()
二、批量修改(修改查詢結果集的值)
調用update()函數便可
Author.objects.all().update(屬性=值,....)
說明:不能批量修改id
四、刪除操做
一、刪除單個對象
obj = Author.objects.get(id=1)
obj.delete()
二、批量刪除
Author.objects.all().delete()
五、F()操做 和 Q()操做
一、F()操做
做用:在執行中獲取某列的值
語法:F(‘列名’)
from django.db.models import F
Author.objects.all().update(age=F('age')+10)
二、Q()操做
做用:在查詢條件中完成或(or)的操做
語法:
from django.db.models import Q
Q(條件1)|Q(條件2)
Author.objects.filter(id=1,age=35)//查詢id爲1而且age爲35
Author.objects.filter(Q(id_exact=1)|Q(age=35),name='王')//查詢id爲1或者age爲35,而且那麼爲王的
用法二:
q = Q()
q.connector = 'or'
q.children.append(('id_exact',1))
q.children.append(('age',35))
Author.objects.filter(q)//查詢id爲1或者age爲35
六、原生的數據庫操做方法
一、查詢
函數:raw()
語法:Entry.objects.raw(sql語句)
二、增刪該
def sql(requset):
with connection.cursor() as cursor:
sql = 'delete from index_author;'
cursor.execute(sql)
return render(......)
七、轉發 與 重定向
一、轉發:
轉發就是將用戶的請求發給另一個視圖進行處理,並將處理結果返回給用戶請求的視圖,最後響應給用戶
表現:地址欄不會發生改變
緣由:只有一次請求,因此地址欄就是最初請求的地址
def query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() return query_views(request)
二、重定向:(推薦使用)
重定向就是告知並響應給用戶哪一個視圖能夠處理用戶的請求,而後用戶在根據響應的地址進行請求,最終獲得結果
表現:地址欄會顯示最後一次請求的地址
緣由:重定向致使瀏覽器向服務器發送了兩次請求
from django.http import HttpResponseRedirect
def query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #重定向,參數是要重定向的地址 return HttpResponseRedirect('/02_query/')
from django.shortcuts import redirect
def query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #重定向,參數是要重定向的地址 return redirect('/02_query/')
from django.shortcuts import reverse
def query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #方向解析,參數是url的別名 url = reverse('query') #重定向,參數是要重定向的地址 return redirect(url)
一、使用後臺管理Models
後臺登陸地址:http://localhost:8000/admin
一、建立後臺管理員
./manage.py createsuperuser
Username:
Email Address:能夠爲空
Password:
Password(agin)
二、基本管理
一、在應用中的admin.py中註冊要管理的數據
一、admin.py
做用:註冊須要管理的Models,只有在此註冊的Model才容許被管理,不然沒法管理
二、註冊Model
from .models import *
admin.site.register(Entry)
三、修改models.py處理顯示內容
後臺默認效果可讀性不高
def __str__(self):
return self.name//將後臺顯示Author object(一條記錄),修改成該對象的name屬性值
在實體類中屬性添加verbose_name="姓名"
name = models.CharField(max_length=30,verbose_name="姓名")//顯示name字段爲姓名
name = models.CharField(max_length=30,verbose_name="aa")//顯示name字段爲Aa
四、經過內部類Meta實現展示的屬性
容許爲每一個model類設置內部類Meta來設置其展現形式
class Author(models.Model):
....
....
class Meta:
一、db_table:指定該實體類對應到表的名稱,該操做必須先同步到數據庫
二、verbose_name:定義該實體類在admin中顯示的名字(複數形式),會在該屬性值的後面加s
三、verbose_name_plural:效果同上,是單數形式
四、ordering:在後臺顯示數據時的排序規則,取值是一個列表,默認是升序,降序在字段前面加‘-’
ordering = ["uphone"]:按照電話號碼升序
ordering = ["-uphone"]:按照電話號碼降序
五、ImageField數據類型
在示例對象中添加該數據類型
一、pip install Pillow
二、picture = models.ImageField(
null=True,upload_to='static/upload/usrimg',verbose_name='頭像')
null = True:由於數據表中原先有數據,如今添加新字段,須要容許爲空
upload_to:表示上傳後在項目中的保存路徑
verbose_name:在後臺顯示的名字
二、高級管理
一、在admin.py中建立管理類,實現高級管理功能
一、定義EntryAdmin類,繼承自admin.ModelAdmin
二、註冊實體類
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
三、容許在EntryAdmin增長的屬性
一、list_display
做用:在顯示實體信息的頁面上,都顯示哪些字段
取值:列表 或 元組
二、list_display_links
做用:定義可以連接到具體實體頁面的連接們
取值:由屬性名組成的元組或列表
注意:取值必需要出如今list_display中,默認爲list_display的第一個字段,
三、list_editable
做用:定義在列表頁面中容許被修改的字段
取值:由屬性名組成的元組或列表
注意:list_editable中的值不能出如今list_display_links
四、search_fields
做用:添加容許被搜索的字段
取值:由屬性組成的元組或列表
五、list_filter
做用:在列表的右側增長過濾器,實現快速篩選
取值:由屬性組成的元組或列表
六、date_hierarchy
做用:在頂部增長一個時間選擇器,因此取值必須是DateField 或 DateTieField的列
七、fields
做用:在實體的詳細頁面中,顯示哪些屬性,並按照什麼樣的順序顯示
取值:由屬性組成的元組或列表,空列表或元組無效
八、fieldsets
做用:在實體的詳細頁面中,對屬性進行分組
注意:fieldsets 與 fields不能共存
語法:
fieldsets = (
#分組1
(‘當前分組的名稱’,{'fields':(屬性1,屬性2...),‘classes’:(‘collapse’)}),
#分組2
(‘當前分組的名稱’,{'fields':(屬性1,屬性2...),‘classes’:(‘collapse’)}),
......
)
‘classes’:(‘collapse’):表示能夠被摺疊
九、filter_horizontal(「必須是具備多對多關係的屬性」)和 filter_vertical(「必須是具備多對多關係的屬性」)
注意:
當兩個屬性與raw_id_fields共存時,效果將會失效
原圖:
filter_horizontal = ('publisher',):
filter_vertical = ("publisher",)
十、raw_id_fields("必須是具備一對多或多對多關係的屬性")
class BookAdmin(admin.ModelAdmin): list_display = ('title','publication_date') #book與publisher是多對一的關係, #book域author是多對多的關係 raw_id_fields = ('publisher','author') filter_horizontal = ('author',)#此處域raw_id_fields("author")共存將失效
原圖:
raw_id_fields = ('publisher','author'):
二、Django鏈接查詢(關係映射)
一、一對一映射(1:1)
一、什麼是一對一
A表中的一條記錄只能與B表中的一條記錄匹配關聯
B表中的一條記錄也只能與A表中的一條記錄相關聯
數據庫中的實現:
A表:設計主鍵
B表:有主鍵,增長一列(做爲外鍵),並應用A表中的主鍵值,還得增長一個惟一約束
二、語法:
在關聯的兩個類的任何一個類中,增長對另一個類的應用
屬性 = models.OneToOneField(Author,null=True)
author = models.OneToOneField(Author,null=True)
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| author_id | int(11) | YES | UNI | NULL | |
+-----------+-------------+------+-----+---------+----------------+
| wife | CREATE TABLE `wife` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`age` int(11) NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `author_id` (`author_id`),
CONSTRAINT `wife_author_id_1672739f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
#編寫Wife實體了類,與Author作一對一關係映射 class Wife(models.Model): name = models.CharField(max_length=30,verbose_name="姓名") age = models.IntegerField(verbose_name='年齡') #指定一對一的關聯關係,引用自Author實體 author = models.OneToOneField(Author,verbose_name='丈夫') class Meta: db_table='wife'
三、查詢
class Wife(models.Model):
name = models.CharField(max_length=30,verbose_name='姓名')
age = models.IntegerField(verbose_name="年齡")
#增長一對一的關係映射
author = models.OneToOneField(Author,null=True,verbose_name='丈夫')
正向查詢:經過wife 找 author
#獲取id爲1的wife的信息
w = Wife.objects.get(id=1)
#在獲取wife關聯的author
a = w.author
def oto_views(requset): #先獲取i的爲1的wife的信息 wife = Wife.objects.get(id=1) #再獲取對應的author author = wife.author return render(requset,'03_oto.html',locals())
反向查詢:經過author 找 wife
a = Author.objects.get(id=1)
w = a.wife
wife 是由Django經過OneToOneField在Author中默認增長的一個屬性,在數據庫中沒有體現
二、一對多映射
一、什麼是一對多
A表中的一條數據能夠與B表中的任意多條數據匹配
B表中的一條數據只能與A表中的一條數據相關聯
二、語法:
在‘多’表中增長外鍵,對‘一’表表中的主鍵進行引用
使用外鍵(Foreign Key)
在‘多’實體中增長:
屬性 = models.ForeignKey(實體類)
pub = models.ForeignKey(Publisher,null=True)
+----+----------+------------------+--------+
| id | title | publication_date | pub_id |
+----+----------+------------------+--------+
| 1 | Python | 1990-01-20 | 1 |
| 2 | HTML/CSS | 1992-12-18 | NULL |
| 3 | Django | 2018-08-18 | 3 |
| 4 | HTML/CSS | 1992-02-18 | 2 |
| 5 | JAVA | 2018-08-19 | 3 |
+----+----------+------------------+--------+
| book | CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(30) NOT NULL,
`publication_date` date NOT NULL,
`publisher_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `book_publisher_id_ac4b162a_fk_publisher_id` (`publisher_id`),#普通索引
CONSTRAINT `book_publisher_id_ac4b162a_fk_publisher_id` FOREIGN KEY (`publisher_id`) REFERENCES `publisher` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
三、查詢
Book(M)和publisher(1)
class Book(models.Model):
#增長一對多的關係
pub = models.ForeignKey(Publisher,null=True,verbose_name="出版社")
一、正向查詢 —— 經過Book 查詢 Publisher
book = Book.objects.get(id=1)
publisher = book.pub
def otm_views(request): #先查詢id爲1的book的信息 book = Book.objects.get(id=1) #在查詢book關聯publisher publisher=book.publisher return render(request,'04_otm.html',locals())
二、反向查詢 - 經過Publisher 查詢 Book
Django會經過ForeignKey()向關聯的類中增長一個隱式屬性:當前類_set,(當前類小寫)
p = Publisher.objects.get(id=1)
bookset = p.book_set.all()//book_set是Django在Publisher實體類中添加book_set屬性
三、多對多映射
一、什麼是多對多
A表中的一條記錄能夠與B表中的任意多條記錄相關聯
B表中的一條記錄能夠與A表中的任意多條記錄相關聯
二、在數據庫中的體現
必須建立第三張表,用於關聯涉及到的兩張表的數據
三、語法:
在涉及的到兩個類中的任意一個類中,均可以對另一個類的多對多的引用
entry=models.ManyToManyField(Entry)
示例:
建立書籍與做者之間的多對多的引用
能夠在書籍實體類中,增長對做者的引用
能夠在做者實體類中,增長對書籍的引用
class Book(models.Model):
........
author=models.ManyToManyField(Author)
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| book_id | int(11) | NO | MUL | NULL | |
| author_id | int(11) | NO | MUL | NULL | |
+-----------+---------+------+-----+---------+----------------+
| book_author | CREATE TABLE `book_author` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_id` int(11) NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `book_author_book_id_author_id_4fda6750_uniq` (`book_id`,`author_id`),#複合惟一索引book_id和author_id不能同時相同
KEY `book_author_author_id_325bf96f_fk_author_id` (`author_id`),#普通索引
CONSTRAINT `book_author_author_id_325bf96f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`),
CONSTRAINT `book_author_book_id_19a45511_fk_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
四、查詢
class Book(models.Model):
........
author=models.ManyToManyField(Author)
正向查詢:經過Book找到對應的全部的Author
#查詢id爲1的書籍的信息
book = Book.objects.get(id=1)
#查詢book對應的全部的做者,經過關聯屬性查詢對應的全部信息
authors = book.author.all()
反向查詢:經過Author查詢全部的Book
Django會經過ManyToManyField()在關聯類中增長一個隱式屬性
屬性名:當前類_set,(類名小寫)
#查詢id爲2的做者信息
author = Author.objects.get(id=2)
#再查詢對應的全部的書籍
bookList = author.book_set.all()
def mtm_views(request): #正向查詢 book =Book.objects.get(id=2) authors = book.author.all() #反向查詢,book_set author = Author.objects.get(id=3) bookList = author.book_set.all() return render(request,'05_mtm.html',locals())
HTTP通訊協議
一、什麼是HTTP
HTTP:Hyper Text Transfer Protocol(超文本傳輸協議)
做用:規範了數據是如何打包以及傳送的
二、請求消息
由請求起始行,請求消息頭,請求主體
請求主題:
post和put兩種提交方式會產生請求主體
三、響應消息
由響應起始行,響應消息頭,響應主體
一、HttpRequest
一、HttpRequest介紹
HttpRequest,在Django中是對請求對象的封裝體現,會封裝請求過程當中全部的信息,
在Django中,HTTPRequest被封裝成了Request被自動傳到了視圖處理函數中
以雙下劃線或單下劃線開頭的不是HTTPRequest協議中的屬性或方法,是Django自動添加的
['COOKIES', 'FILES', 'GET', 'META', 'POST', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_encoding', '_get_post', '_get_raw_host', '_get_scheme', '_initialize_handlers', '_load_post_and_files', '_mark_post_parse_error', '_messages', '_post_parse_error', '_read_started', '_set_post', '_stream', '_upload_handlers', 'body', 'build_absolute_uri', 'close', 'content_params', 'content_type', 'csrf_processing_done', 'encoding', 'environ', 'get_full_path', 'get_host', 'get_port', 'get_raw_uri', 'get_signed_cookie', 'is_ajax', 'is_secure', 'method', 'parse_file_upload', 'path', 'path_info', 'read', 'readline', 'readlines', 'resolver_match', 'scheme', 'session', 'upload_handlers', 'user', 'xreadlines']
二、HTTPRequest中的主要內容
一、request.scheme:請求協議
二、request.body:請求主題(只有post和put請求方式時纔會有請求主題)
三、request.path:請求路徑
四、request.get_host():請求的主機地址或域名
五、request.method:獲取請求方法
六、request.GET:封裝了GET請求方式提交的數據
七、request.POST:封裝了POST請求方式提交的數據
說明:
GET,POST的返回值都是一個字典,字典的值是一個列表,可是經過request.GET['key']取出的一個字符串,(爲何?)
答案:Django中經過重寫__getitem__方法實現的
''' QueryDict.__getitem__(key) 返回給出的 key 的值。若是key 具備多個值,__getitem__() 返回最後(最新)的值。若是 key 不存在, 則引起django.utils.datastructures.MultiValueDictKeyError。( 它是Python 標準KeyError 的一個子類,因此你仍然能夠堅持捕獲KeyError。) 總結:Django中經過重寫__getitem__方法實現的 ''' class MyDict(): def __init__(self,iterable): self.data = iterable def __getitem__(self, item): return self.data[item][-1] dict = { 'name':['xdl','gj'], 'age':[25] } myDict = MyDict(dict) print(type(myDict))#<class '__main__.MyDict'> print(myDict['name'])#gj
八、request.COOKIES:封裝了cookie的數據
九、request.META:封裝了請求的元數據
request.META["HTTP_REFERER"]:封裝了請求的源地址
def requset_views(request): #request,類型就是HTTPRequest #request,封裝的是全部與請求相關的內容 #print(dir(request)) #請求協議(方案),http scheme = request.scheme #請求主體 body = request.body #請求資源的具體路徑,根相對路徑,/01_requset/ path = request.path #請求的主機地址或域名,127.0.0.1:8000 host = request.get_host() #請求方式,GET method = request.method #get方式請求的數據,獲得的是一個字典,<QueryDict: {}> get = request.GET #post方式請求數據,<QueryDict: {}> post = request.POST #cookie中的數據,返回的是一個字典 # {'csrftoken': 'w1TDCKqZakTz9IKn94luPeFjefTsGdDnRqGxzXdGJ5yNOQaWfeJC5MbUw0KRPWzo', # 'sessionid': '702s33knczrluqmeh15m9rvbasptd39i'} cookies = request.COOKIES #請求元數據,返回的是一個字典 meta = request.META return render(request,'01_request.html',locals())
三、獲取請求提交的數據
一、get請求方式
request.GET["名稱"]
一、使用表單提交數據
<form></form>
二、經過超連接拼接查詢字符串
<a href="地址?參數1&參數2..."></a>
此種方式,屬於http標準,任何語言均可以使用
Django中經過URL傳遞參數
url(r'01_test/(\d+)',test_views)
此種方式,非http標準的,屬於Django標準
二、post請求方式
request.POST["名稱"]
CSRF:Cross-Site Request Forgery(假裝):跨站點假裝攻擊
解決方案:
一、取消CSRF的驗證
刪除settings.py中MIDDLEWARE中的'CsrfViewMiddleware'中間件
二、開放驗證權限,無需驗證,直接進入
在視圖處理函數之上增長一個裝飾器@crsf_protect
須要引包:from django.views.decorators.csrf import csrf_protect
三、必需要經過驗證後才能夠請求
在模板中<form>下第一行增長:{% scrf_token %}
在表單裏面會出現一個隱藏域,value是一個可變的字符串
<input type='hidden' name='csrfmiddlewaretoken' value='hE2u8FkzeReMYlfzj8CUHPUwEVqURdc6C3Po5S7gNCT0DtF8pi02Xnq7WGhj0W87' />
四、Django中的表單處理
表單頁面的get和post請求是由同一個視圖(views)處理的,經過request.method判斷
def login_views(request): if request.method == 'GET': return render(request,'03_login.html') else: return HttpResponse('用戶名:%s,密碼:%s'%(request.POST['uname'],request.POST['upwd']))
二、使用forms模塊處理表單
一、forms模塊的做用
經過forms模塊,容許將表單與class相結合,容許經過class生成表單
二、使用forms模塊
一、建立forms.py文件(在應用中建立)
二、導入forms
form django import forms
三、建立class,必須繼承自forms.Form一個class對應成一個表單
class LoginForm(forms.Form):
pass
四、在class中建立屬性(不用建立提交按鈕)
一個屬性對應一個表單控件
# 表示評論內容的表單控件 class RemarkForm(forms.Form): # 評論標題-文本框 subject = forms.CharField(label='標題') # Email - type=‘Email’ email = forms.EmailField(label="郵箱") #評論內容-文本域 message = forms.CharField(label="內容",widget=forms.Textarea)#widget=forms.PasswordInput表示密碼框 #好評,中平,差評-select topic_choices = ( (1,"好評"), (2,"中評"), (3,"差評")) topic = forms.ChoiceField(label='評價',choices=topic_choices) #是否保存 isSaved = forms.BooleanField(label='是否保存')
三、在模板中解析form對象
一、注意
一、須要自定義<form></form>
二、須要自定義按鈕<input type='submit'>
二、處理方法
在視圖中建立forms.Form的對象,併發送到模板中
示例:
form = RemarkForm()
return render(request,'xx.html',locals())
一、手動解析
在模板中:
{% for field in form %}
{{field.lable}}:表示控件前面顯示的文本
{{field}}:表示的就是控件
{% endfor %}
二、自動解析
一、{{form.as_p}}
將form對象中的每一個屬性使用p標記包裹起來,再顯示在網頁上
二、{{form.as_ul}}
將form對象中的每一個屬性使用li標籤包裹起來,再顯示在網頁上
注意:必須手動提供<ol></ol>或<ul></ul>
三、{{form.as_table}}
將form對象中的每一個屬性使用tr標籤包裹起來,再顯示在網頁上
注意:必須手動提供<table></table>
四、在視圖中,經過forms.Form自動獲取表單數據
一、經過forms.Form的構造函數,接收post數據
form = XXXForm(requset.POST)
二、須要讓form經過驗證後,再取值(必需要驗證)
form.is_valid()
返回True:提交的數據已經經過驗證,容許接收表單提交的數據
返回False:提交的數據驗證未經過,沒法取值
三、獲取表單中的數據
經過form.cleaned_data(字典)接收提交的數據
def register_views(request): if request.method =="GET": form = RegisterForm() return render(request,'06_register.html',locals()) else: form = RegisterForm(request.POST) if form.is_valid(): cd = form.cleaned_data try: User.objects.get(uname=cd['uname']) return HttpResponse('用戶名已存在') except ObjectDoesNotExist: User.objects.create(**cd) return HttpResponse("註冊成功")
一、forms模塊
一、forms的高級處理
將Models和Forms結合到一塊兒使用
將Forms中的類和Models中的類關聯到一塊兒,實現屬性的共享
一、在forms.py中建立class,繼承自forms.ModelForm
二、建立內部類:Meta,關聯Form和Model
屬性:
一、model:指定要關聯的Model類
二、fields:指定從Model中取哪些字段生成控件
一、取值:"__all__",所有的屬性都要生成控件
二、取值:列表或元祖,聲明容許生成控件的屬性名稱
三、labels:指定每一個屬性所關聯的label,取值爲字典
labels={
'屬性名':"label文本",
'屬性名':"label文本",
.........
}
#建立class表示登陸的表單,要關聯Users實體類 class UserLoginForm(forms.ModelForm): class Meta: #指定關聯的model model = User #指定要生成的控件字段 fields = ["uname","upwd"] #指定每一個控件對應的label labels={ "uname":"用戶名", "upwd":"密碼", }
二、內置小部件
一、什麼是小部件
小部件(widget),表示的是生成到頁面中的控件的類型以及其餘的html屬性
二、經常使用的小部件
一、TextInput:type=「text」
二、NumberInput:type=「number」
三、PasswordInput:type=「password」
四、EmailInput:type=「email」
五、URLInput:type=」url「
六、HiddenInput:type=「hidden」
七、CheckboxInput:type=「checkbox」
八、Textarea:<Textarea></Textarea>
九、Select:<Select></Select>
三、小部件的使用
一、繼承自forms.Form
一、基本版
只指定控件的類型
屬性=forms.CharField(
lable="標籤",
widget=forms.小部件的類型
)
示例:
upwd=forms.CharField(label=「密碼」,widget=forms.PasswordInput)
二、高級版
指定控件類型以外還容許設置html屬性
屬性=forms.CharField(
label="標籤",
widget=forms.小部件類型(
attrs = {
"html屬性名":"屬性值",
"html屬性名":"屬性值",
......
}
)
)
class WidgetForm(forms.Form): uname = forms.CharField( label="用戶名稱", widget=forms.TextInput( attrs={ 'name':'user_name', 'placeholder':"請輸入用戶名稱", 'class':'form-control', } ) ) upwd = forms.CharField( label="用戶密碼", widget=forms.PasswordInput( attrs={ 'name':'user_pwd', 'placeholder':'請輸入密碼', 'class':'form-control', } ) )
二、繼承自forms.ModelForm
class Widget2Form(forms.ModelForm):
class Meta:
model = User
fields= "__all__"
labels={
"屬性1":"標籤1",
"屬性2":"標籤2",
....
}
widgets={
"屬性1":forms.小部件類型(attrs={}),
"屬性2":forms.小部件類型(attrs={}),
........
}
class Widget2Form(forms.ModelForm): class Meta: model=User fields=("uname","upwd") labels={ "uname":'用戶名稱', "upwd":"用戶密碼", } widgets={ 'uname':forms.TextInput( attrs={ "placeholder":'請輸入用戶名' } ), 'upwd':forms.PasswordInput( attrs={ 'placeholder':"請輸入密碼" } ) }
二、cookies
一、什麼是cookies
cookies是一種數據的存儲技術,只能保存字符串
容許將一段文本保存在客戶端上(瀏覽器)的一種技術,並能夠長時間保存
二、cookies的使用場合
一、記住密碼
二、保存搜索關鍵詞
三、在Django中使用cookies
一、設置cookies的值(將數據保存客戶端)
語法:
響應對象.set_cookie(key,value,[expires])
key:cookie的名字
value:cookie的值
expires:保存時間,以s爲單位,若是不給該參數,則瀏覽器關閉,cookie失效
示例:
響應對象.set_cookie('uname','xdl',60*60*24*366)
響應對象:HttpResponse,render,HttpResponseRedirect,redirect
一、不使用模板(HttpResponse)
resp = HttpResponse("給客戶端的一句話")
resp.set_cookie('key','value',expires)
return resp
二、使用模板(render)
resp = render(reuqest,'xxx.html',locals())
resp.set_cookie('key','value',expires)
return resp
三、重定向(HttpResponseRedirect/redirect)
resp = HttpResponseRedirect('/地址/')
resp.set_cookie('key','value',expires)
return resp
二、獲取cookies的值(將數據從客戶端中獲取出來)
經過request.COOKITES(返回的是一個字典,經過鍵值能夠取值)
獲取當前訪問站點下全部的cookies的信息
三、刪除cookie
響應對象.delete_cookie('key')
三、session-會話
一、什麼是session
session(會話),實際上就是在服務器上爲每一個瀏覽器開闢的一段空間,用於保存相關的請求信息
二、session的使用場合
session也是爲了存儲數據而存在的
一般會把服務器常常要用到的數據保存進去
三、Django中使用session
一、設置session的值
request.session['key']=value
request.session.set_expiry(time):
設置session的過時時間,若是設置爲0的話,則表示關閉瀏覽器session就失效
二、獲取session的值
value = request.session['key']
value = request.session.get('key')
三、刪除session的值
del request.session['key']
四、在setting.py中,有關session的設置
一、SESSION_COOKIE_AGE
做用:設置sessionID在cookies中的保存時長,默認爲15天
示例:
SESSION_COOKIE_AGE=60*6024
二、SESSION_EXPIRE_AT_BROWSER_CLOSE(建議使用)
做用:設置關閉瀏覽器時清除服務器上對象的session空間
示例:
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
cookie 存取中文
def setCookie_views(request): uname = '張三丰' #將uname轉化爲unicode uname = json.dumps(uname) resp = HttpResponse('set cookie ok') resp.set_cookie('name',uname) return resp def getCookie_views(requset): uname = requset.COOKIES['name'] #將unicode碼轉換爲中文 uname = json.loads(uname) return HttpResponse(uname)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript" src="/static/js/jquery-1.11.3.js"></script> <script type="text/javascript" src="/static/js/jquery.cookie.js"></script> <script> $(function(){ var uname = $.cookie('name') //將Unicode碼轉換爲中文 uname = JSON.parse(uname) console.log(uname) }); </script> </body> </html>
上傳圖片
前段頁面:
上傳圖片
<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="pic" id="pic"> <button type="submit">提交</button> </form>
訪問圖片:經過views函數返回這個對象集合,而後在前端循環獲取圖片路徑.url
{% for show in p %} {% if show.pic %} <img src="{{ show.pic.url }}"> {% endif %} {% endfor %}
後端配置:
配置settings文件
MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace('\\','/') MEDIA_URL = '/media/'
配置urls文件,主路由文件
from django.conf.urls import url, include from django.contrib import admin from sale import views from django.conf import settings from django.conf.urls.static import static urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$',views.index,name='index'), url(r'^userinfo/',include('userinfo.urls')), ]+ static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
views.py視圖
def salecar(request): new_a = Aid()#實體類 pic = request.FILES.get('pic') new_a.pic = pic new_a.save() return render(request,'infomessage.html')