Django框架簡介
標簽: django
框架(framework),指為解決一個開放性的問題而設計的具有一 定約束性的支撐結構,使用框架可以幫助你快速開發特定的系統。
常見的python web框架
`Full-Stack Framework`(全棧框架)
Django、web2py、TurboGears、Pylons、......
`Non Full-Stack Framework`(非全棧框架)
tornado、Flask、Bottle、webpy、pyramid.....
部署Django環境
python 3.5.2
Django==1.11.5
PyMySQL==0.7.11
pytz==2017.2
下載安裝Django模塊
方法一:使用pip工具
更新pip的版本
python -m pip install --upgrade pip
首先要確保安裝了pip工具
pip install Django
方法二:使用git
$ git clone git://github.com/django/django.git $ pip install -e django/
方法三:下載Django的py包,然后使用python命令安裝
檢測是否安裝成功
In [1]: import django In [2]: django.VERSION Out[2]: (1, 11, 4, u'final', 0)
安裝數據庫
django默認提供了Sqlite數據庫
安裝python和mysql的連接模塊。
pip install PyMySQL 連接數據庫
啟動Apache
Django-admin命令
>django-admin.py help
Type 'django-admin.py help <subcomm
Available subcommands:
[django]
check 檢查Django項目的完整性
compilemessages 編輯語言文件
createcachetable
dbshell 進入Django dbshell
diffsettings 查看你的配置和Django的默認配置有和不同
dumpdata 導出數據
flush 清空數據庫
inspectdb
loaddata 導入數據
makemessages 創建語言文件
makemigrations 生成數據庫同步腳本
migrate 同步數據庫
runserver 運行開發服務器
sendtestemail
shell 進入django shell
showmigrations 查看生成數據庫的同步腳本
sqlflush 查看生成清空數據庫的腳本
sqlmigrate 查看數據庫同步的sql語句
sqlsequencereset
squashmigrations
startapp 創建一個app
startproject 創建一個項目
test
testserver
查看指定命令的幫助文檔
>django-admin.py help startproject
usage: django-admin.py startproject [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color] [--template TEMPLATE]
[--extension EXTENSIONS] [--name FILES]
name [directory]
Creates a Django project directory structure for the given project name in th
current directory or optionally in the given directory.
positional arguments:
name Name of the application or project.
directory Optional destination directory
optional arguments:
-h, --help show this help message and exit
創建Django第一個app(helloworld)
[root@miner-k ~]# mkdir /app
[root@miner-k ~]# cd /app/
[root@miner-k app]# django-admin startproject mysite
[root@miner-k app]# tree .
.
└── mysite #Django項目的名稱,剛才創建的項目名稱
├── manage.py #命令行實用程序,與Django進行交互。
└── mysite
├── __init__.py
├── settings.py #配置文件
├── urls.py #url的設置
└── wsgi.py #動態網關接口文件
Django-admin.py是Django的一個用于管理任務的命令工具,manage.py是對Django-admin.py的簡單包裝,每一個Django project里面都會包含一個manage.py
[root@miner-k mysite]# python manage.py help
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
創建一個名為hello的app
[root@miner-k mysite]# python manage.py startapp hello
一般不同的APP負責不同的功能,一個app負責一個功能。
[root@miner-k mysite]# tree hello/
blog/
├── admin.py #管理后臺的配置
├── apps.py #app的配置
├── __init__.py
├── migrations #數據庫的管理
│ └── __init__.py
├── models.py #模型代碼的配置
├── tests.py #單元測試
└── views.py #業務代碼
登錄到Django的后臺
生成同步數據庫的腳本
D:\pythonwork\django\mysite>python manage.py makemigrations No changes detected
同步數據
D:\pythonwork\django\mysite>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying sessions.0001_initial... OK
創建超級用戶以及密碼(密碼不能太短)
D:\pythonwork\django\mysite>python35 manage.py createsuperuser Username (leave blank to use 'administrator'): admin Email address: Password: Password (again): Superuser created successfully.
修改超級用戶的密碼
D:\pythonwork\django\mysite>python35 manage.py changepassword admin Changing password for user 'admin' Password:
啟動服務
D:\pythonwork\django\mysite>python35 manage.py runserver Performing system checks... System check identified no issues (0 silenced). October 10, 2017 - 20:52:07 Django version 1.11.5, using settings 'mysite.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.
登錄后臺
登錄后臺的URL:http://127.0.0.1:8000/admin/
設置服務監控的端口
啟動的時候指定監聽的端口
D:\pythonwork\django\mysite>python35 manage.py runserver 8080
Performing system checks...
System check identified no issues (0 silenced).
September 12, 2017 - 22:13:32
Django version 1.11.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.
創建一個網頁
靜態文件存放到app的目錄下
默認情況下
static 目錄:存放css、js、圖片等靜態文件
templates 目錄:存放模板
在app中配置
修改hello的app目錄下的views.py定義一個業務請求處理的函數
from django.shortcuts import render # Create your views here. def hello(request): return render(request,'table.html ')
定義一個模板并引用靜態文件
在app的目錄下創建兩個目錄
static
和templates
將static目錄下存放CSS、js格式的文件
在template目錄下存放table.html文件
在項目mysite目錄中配置
在settings.py里面的
INSTALLED_APPS
中加入hello
,將新建的app增加到項目中。INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'hello', ]
在urls.py里面定義url地址
from django.conf.urls import url from django.contrib import admin from hello import views #從指定的app中導入views '''url(URL路徑正則表達式,app中views的函數,別名)''' urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^hello/', views.hello,name='hello'), ]
啟動服務
訪問測試
訪問網站:http://127.0.0.1:8000/hello/
靜態文件、模板存放到工程目錄下
修改seting.py文件
'''在DIRS中指定模板的目錄'''
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['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',
],
},
},
]
'''指定靜態文件的目錄'''
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
在app中設置URL
上面的URL的配置是在工程的urls.py中設置訪問的URL,現在為了方便管理不同的URL,需要在不同的app下設置URL
工程中的urls.py配置
''' 包含app中URL的配置文件
1.導入incloude():
from django.conf.urls import url, include
2. 增加URL的參數:
url(r'^blog/', include('blog.urls'))
r'^blog/' :訪問的后綴
include('blog.urls'):指定包含的URL的存放位置。blog目錄下的urls
'''
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('hello.urls')),
]
app中的urls.py的配置
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello),
]
注意:訪問URL時,URL是項目中URL中配置加app中的URL。如果在工程中的URl中設置url(r'^abc/', include('hello.urls')),
在app中設置url(r'^hello/$', views.hello),
訪問時輸入的URl為http://127.0.0.1:8000/abc/hello/
MTV和MVC
在鉆研更多代碼之前,讓我們先花點時間考慮下 Django 數據驅動 Web 應用的總體設計。
Django 的設計鼓勵松耦合及對應用程序中不同部分的嚴格分割。 遵循這個理念的話,要想修改應用的某部分而不影響其它部分就比較容易了。 在視圖函數中,我們已經討論了通過模板系統把業務邏輯和表現邏輯分隔開的重要性。 在數據庫層中,我們對數據訪問邏輯也應用了同樣的理念。
把數據存取邏輯、業務邏輯和表現邏輯組合在一起的概念有時被稱為軟件架構的 Model-View-Controller (MVC)模式。 在這個模式中, Model 代表數據存取層,View 代表的是系統中選擇顯示什么和怎么顯示的部分,Controller 指的是系統中根據用戶輸入并視需要訪問模型,以決定使用哪個視圖的那部分。
Django 緊緊地遵循這種 MVC 模式,可以稱得上是一種 MVC 框架。 以下是 Django 中 M、V 和 C 各自的含義:
- M ,數據存取部分,由django數據庫層處理。
- V ,選擇顯示哪些數據要顯示以及怎樣顯示的部分,由視圖和模板處理。
- C ,根據用戶輸入委派視圖的部分,由 Django 框架根據 URLconf 設置,對給定 URL 調用適當的 Python 函數。
由于 C 由框架自行處理,而 Django 里更關注的是模型(Model)、模板(Template)和視圖(Views),Django 也被稱為 MTV 框架 。在MTV 開發模式中:
- M 代表模型(Model),即數據存取層。 該層處理與數據相關的所有事務: 如何存取、如何驗證有效性、包含哪些行為以及數據之間的關系等。
- T 代表模板(Template),即表現層。 該層處理與表現相關的決定: 如何在頁面或其他類型文檔中進行顯示。
- V 代表視圖(View),即業務邏輯層。 該層包含存取模型及調取恰當模板的相關邏輯。 你可以把它看作模型與模板之間的橋梁。
如果你熟悉其它的 MVC Web開發框架,比方說 Ruby on Rails,你可能會認為 Django 視圖是控制器,而 Django 模板是視圖。 很不幸,這是對 MVC 不同詮釋所引起的錯誤認識。 在 Django 對 MVC 的詮釋中,視圖用來描述要展現給用戶的數據;不是數據 如何展現 ,而且展現 哪些 數據。 相比之下,Ruby on Rails 及一些同類框架提倡控制器負責決定向用戶展現哪些數據,而視圖則僅決定 如何 展現數據,而不是展現 哪些 數據。
MTV的響應模式如下所示:
- Web服務器(中間件)收到一個http請求
- Django在URLconf里查找對應的視圖(View)函數來處理http請求
- 視圖函數調用相應的數據模型來存取數據、調用相應的模板向用戶展示頁面
- 視圖函數處理結束后返回一個http的響應給Web服務器
- Web服務器將響應發送給客戶端
Django中的配置文件的簡介
url.py詳解
Django 決定要使用的根URLconf 模塊。通常,這個值就是ROOT_URLCONF 的設置,但是如果進來的HttpRequest 對象具有一個urlconf 屬性(通過中間件request processing 設置),則使用這個值來替換ROOT_URLCONF 設置。
url.py:URL分發器(路由配置文件)
URL配置(URLconf)就像配置Django所支持的網站目錄,他的本質是URL模式以及要為該URL模式調用的視圖函數之間的映射表。
URL模式:
urlpatterns = [
url(正則表達式,view函數,參數,別名,前綴),
]
#url的函數定義
url(regex, view, kwargs=None, name=None):
實例:正則表達式的匹配
下面是一個簡單的 URLconf:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
注:
- 若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
- 不需要添加一個前導的反斜杠,因為每個URL 都有。例如,應該是^articles 而不是 ^/articles。
- 每個正則表達式前面的’r’ 是可選的但是建議加上。它告訴Python 這個字符串是“原始的” —— 字符串中任何字符都不應該轉義。
一些請求的例子:
- /articles/2005/03/ 請求將匹配列表中的第三個模式。Django
將調用函數views.month_archive(request, ‘2005’, ‘03’)。 - /articles/2005/3/ 不匹配任何URL 模式,因為列表中的第三個模式要求月份應該是兩個數字。
- /articles/2003/
將匹配列表中的第一個模式不是第二個,因為模式按順序匹配,第一個會首先測試是否匹配。請像這樣自由插入一些特殊的情況來探測匹配的次序。 - /articles/2003 不匹配任何一個模式,因為每個模式要求URL 以一個斜線結尾。
- /articles/2003/03/03/ 將匹配最后一個模式。Django 將調用函數views.article_detail(request, ‘2003’, ‘03’, ‘03’)。
正則表達中傳遞參數(命名組)
上面的示例使用簡單的、沒有命名的正則表達式組(通過圓括號)來捕獲URL 中的值并以位置 參數傳遞給視圖。在更高級的用法中,可以使用命名的正則表達式組來捕獲URL 中的值并以關鍵字 參數傳遞給視圖。
在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式。
下面是以上URLconf 使用命名組的重寫:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數。例如:
- /articles/2005/03/ 請求將調用views.month_archive(request, year=’2005’, month=’03’)函數,而不是views.month_archive(request, ‘2005’, ‘03’)。
- /articles/2003/03/03/ 請求將調用函數views.article_detail(request, year=’2003’, month=’03’, day=’03’)。
在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你可以在你的視圖函數定義中重新安排參數的順序。當然,這些好處是以簡潔為代價;conf
命名組和傳遞參數的區別:
該方法傳遞的參數是變量,可以根據客戶端等的不同而變化,但是使用ru()中傳遞的參數是固定值。
實例:傳遞參數
urls.py
from django.conf.urls import url
from hello import views
'''向views中的hello函數中傳遞參數a'''
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
]
views.py
from django.shortcuts import render
from django.contrib.auth.models import User
# Create your views here.
'''函數hello接收參數a,否則會報錯'''
def hello(request,a):
user_list = User.objects.all()
print(a)
return render(request,"table.html ",{'user_list':user_list})
URL的分解器,include函數
通常一個URL分解器對應一個URL匹配模塊,它可以包含多個URL模式,也可以包含多個其他的URL分解器。通常這種包含關系結構設計,實現了Django對URL的層級解析。
工程中的urls.py配置
''' 包含app中URL的配置文件
1.導入incloude():
from django.conf.urls import url, include
2. 增加URL的參數:
url(r'^blog/', include('blog.urls'))
r'^blog/' :訪問的后綴
include('blog.urls'):指定包含的URL的存放位置。blog目錄下的urls模塊
'''
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('hello.urls')),
]
app中的urls.py的配置
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello),
]
注意:訪問URL時,URL是項目中URL中配置加app中的URL。如果在工程中的URl中設置url(r'^abc/', include('hello.urls')),
在app中設置url(r'^hello/$', views.hello),
訪問時輸入的URl為http://127.0.0.1:8000/abc/hello/
總結
urls.py中,需要配置訪問時的URL
設置urls.py的主目錄
'''在工程目錄中的seting.py中設置,設置工程mysite下的urls為主URL的配置文件''' ROOT_URLCONF = 'mysite.urls'
配置方法:
'''配置URL的正則表達式以及對應的URL對應的操作(函數)''' from django.conf.urls import url urlpatterns = [ url('正則表達式', '操作函數','參數','別名','前綴'), ]
為方便管理URL設置層目錄include函數
''' 包含app中URL的配置文件 1.導入incloude(): from django.conf.urls import url, include 2. 增加URL的參數: url(r'^blog/', include('blog.urls')) r'^blog/' :訪問的后綴 include('blog.urls'):指定包含的URL的存放位置。blog目錄下的urls模塊 ''' from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('hello.urls')), ]
view.py簡介
Django 使用Request 對象和Response 對象在系統間傳遞狀態。
當請求一個頁面時,Django會建立一個包含請求元數據的 HttpRequest 對象。 當Django 加載對應的視圖時,HttpRequest 對象將作為視圖函數的第一個參數。每個視圖會返回一個HttpResponse 對象。
from django.shortcuts import render
from django.contrib.auth.models import User
from django.http import HttpRequest,HttpResponse
def hello(request,a):
user_list = User.objects.all()
print(a)
return render(request,"table.html ",{'user_list':user_list})
HttpRequest對象
在函數最開始的第一個參數,request是HttpRequest的實例。
屬性
HttpRequest.scheme
一個字符串,表示請求的方案(通常是http 或https)
HttpRequest.body
一個字節字符串,表示原始HTTP 請求的正文。它對于處理非HTML 形式的數據非常有用:二進制圖像、XML等。 如果要處理常規的表單數據,應該使用HttpRequest.POST。
HttpRequest.path
一個字符串,表示請求的頁面的完整路徑,不包含域名。例如:”/music/bands/the_beatles/”
HttpRequest.method
一個字符串,表示請求使用的HTTP 方法。必須使用大寫
if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()
HttpRequest.GET
一個類似于字典的對象,包含HTTP GET 的所有參數
HttpRequest.POST
一個包含所有給定的HTTP POST參數的類字典對象,提供了包含表單數據的請求。詳情請參考下面的QueryDict 文檔。如果需要訪問請求中的原始或非表單數據,可以使用HttpRequest.body 屬性。
POST 請求可以帶有空的POST 字典 —— 如果通過HTTP POST 方法請求一個表單但是沒有包含表單數據的話。因此,不應該使用if request.POST 來檢查使用的是否是POST 方法;應該使用if request.method == “POST”(參見上文)。|
注意:POST 不包含上傳的文件信息
HttpRequest.COOKIES
一個標準的Python 字典,包含所有的cookie。鍵和值都為字符串
HttpRequest.FILES
一個類似于字典的對象,包含所有的上傳文件。FILES 中的每個鍵為 中的name。
注意,FILES 只有在請求的方法為POST 且提交的 帶有enctype=”multipart/form-data” 的情況下才會包含數據。否則,FILES 將為一個空的類似于字典的對象
HttpRequest.META
一個標準的Python 字典,包含所有的HTTP 頭部。具體的頭部信息取決于客戶端和服務器,下面是一些示例:
CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。
CONTENT_TYPE —— 請求的正文的MIME 類型。
HTTP_ACCEPT —— 響應可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。
HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。
HTTP_HOST —— 客服端發送的HTTP Host 頭部。
HTTP_REFERER —— Referring 頁面。
HTTP_USER_AGENT —— 客戶端的user-agent 字符串。
QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。
REMOTE_ADDR —— 客戶端的IP 地址。
REMOTE_HOST —— 客戶端的主機名。
REMOTE_USER —— 服務器認證后的用戶。
REQUEST_METHOD —— 一個字符串,例如”GET” 或”POST”。
SERVER_NAME —— 服務器的主機名。
SERVER_PORT —— 服務器的端口(是一個字符串)。
從上面可以看到,除CONTENT_LENGTH 和CONTENT_TYPE 之外,請求中的任何HTTP 頭部轉換為META 的鍵時,都會將所有字母大寫并將連接符替換為下劃線最后加上HTTP_ 前綴。所以,一個叫做X-Bender 的頭部將轉換成META 中的HTTP_X_BENDER 鍵。HttpRequest.user
一個AUTH_USER_MODEL 類型的對象,表示當前登錄的用戶。如果用戶當前沒有登錄,user 將設置為django.contrib.auth.models.AnonymousUser 的一個實例。你可以通過is_authenticated() 區分它們,像這樣:
if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.
user 只有當Django 啟用AuthenticationMiddleware 中間件時才可用。更多信息,參見Django 中的用戶認證。
HttpRequest.session
一個既可讀又可寫的類似于字典的對象,表示當前的會話。只有當Django 啟用會話的支持時才可用
Response對象
每一個view請求處理方法必須有一個HttpResponse對象的
傳遞字符串
典型的應用是傳遞一個字符串作為頁面的內容到HttpResponse 構造函數:
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")
如果你想增量增加內容,你可以將response 看做一個類文件對象
>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")
Django的快捷函數
render
格式:
render(request, template_name[, context][, context_instance][, content_type][, status][, current_app][, dirs][, using])[source]
結合一個給定的模板和一個給定的上下文字典,并返回一個渲染后的 HttpResponse 對象
必選參數:
request:該request用于生成response
template_name:要使用的模板的完整名稱或者模板名稱的一個序列。
可選參數:
content_type:生成的文檔要使用的MIME 類型。默認為DEFAULT_CONTENT_TYPE 設置的值
status:響應的狀態碼。默認為200
下面的示例渲染模板myapp/index.html,MIME 類型為application/xhtml+xml:
from django.shortcuts import render
def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {"foo": "bar"},
content_type="application/xhtml+xml")
這個示例等同于:
from django.http import HttpResponse
from django.template import RequestContext, loader
def my_view(request):
# View code here...
t = loader.get_template('myapp/index.html')
c = RequestContext(request, {'foo': 'bar'})
return HttpResponse(t.render(c),
content_type="application/xhtml+xml")
render_to_response
格式:
render_to_response(template_name[, context][, context_instance][, content_type][, status][, dirs][, using])[source]
根據一個給定的上下文字典渲染一個給定的目標,并返回渲染后的HttpResponse
必選參數:
template_name:要使用的模板的完整名稱或者模板名稱的一個序列。如果給出的是一個序列,將使用存在的第一個模板。
可選參數:
content_type:生成的文檔要使用的MIME 類型。默認為DEFAULT_CONTENT_TYPE 設置的值
status:響應的狀態碼。默認為200
實例:
下面的示例渲染模板myapp/index.html,MIIME 類型為application/xhtml+xml:
from django.shortcuts import render_to_response
def my_view(request):
# View code here...
return render_to_response('myapp/index.html', {"foo": "bar"},
content_type="application/xhtml+xml")
這個示例等同于:
from django.http import HttpResponse
from django.template import Context, loader
def my_view(request):
# View code here...
t = loader.get_template('myapp/index.html')
c = Context({'foo': 'bar'})
return HttpResponse(t.render(c),
content_type="application/xhtml+xml")
重定向
redirect(to, [permanent=False, ]*args, **kwargs)[source]
為傳遞進來的參數返回HttpResponseRedirect 給正確的URL 。
參數可以是:
- 一個模型:將調用模型的get_absolute_url() 函數
- 一個視圖,可以帶有參數:將使用urlresolvers.reverse 來反向解析名稱
- 一個絕對的或相對的URL,將原封不動的作為重定向的位置。
默認返回一個臨時的重定向;傳遞permanent=True 可以返回一個永久的重定向
示例:
通過傳遞一個對象;將調用get_absolute_url() 方法來獲取重定向的URL:
from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)
通過傳遞一個視圖的名稱,可以帶有位置參數和關鍵字參數;將使用reverse() 方法反向解析URL:
def my_view(request): ... return redirect('some-view-name', foo='bar')
傳遞要重定向的一個硬編碼的URL:
def my_view(request): ... return redirect('/some/url/')
也可以是一個完整的URL:
def my_view(request): ... return redirect('http://example.com/')
默認情況下,redirect() 返回一個臨時重定向。以上所有的形式都接收一個permanent 參數;如果設置為True,將返回一個永久的重定向:
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
HttpResponse子類
Django包含了一系列的HttpResponse衍生類(子類),用來處理不同類型的HTTP 響應(response)。與 HttpResponse相同, 這些衍生類(子類)存在于django.http之中。
class HttpResponseRedirect
構造函數的第一個參數是必要的 — 用來重定向的地址。這些能夠是完全特定的URL地址(比如,’http://www.yahoo.com/search/‘),或者是一個不包含域名的絕對路徑地址(例如, ‘/search/’)。關于構造函數的其他參數,可以參見 HttpResponse。注意!這個響應會返回一個302的HTTP狀態碼。
url
這個只讀屬性,代表響應將會重定向的URL地址(相當于Location response hader)。class HttpResponsePermanentRedirect
與HttpResponseRedirect一樣,但是它會返回一個永久的重定向(HTTP狀態碼301)而不是一個“found”重定向(狀態碼302)。class HttpResponseNotModified
構造函數不會有任何的參數,并且不應該向這個響應(response)中加入內容(content)。使用此選項可指定自用戶上次請求(狀態代碼304)以來尚未修改頁面。class HttpResponseBadRequest
與HttpResponse的行為類似,但是使用了一個400的狀態碼。class HttpResponseNotFound
與HttpResponse的行為類似,但是使用的404狀態碼。class HttpResponseForbidden
與HttpResponse類似,但使用403狀態代碼。
數據庫
在項目的目錄下setings.py中
#setings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
mysql:
引擎的名稱:django.db.backends.mysql
mysql的驅動程序:
- MySQLdb是一個由Andy Dustman開發,已經發展并支持十多年的一個本地驅動。
- mysqlclient是MySQLdb的一個分支,它與python3有著特別好的契合并且可以作為MySQLdb的直接替代。在書寫這篇的時候,這是在Django使用MySQL的推薦的選擇。
- MySQL Connector/Python是一個來自Oracle的純python驅動,它不需要MySQL client庫或在標準庫之外的任何Python模塊。
- PyMySQL(純python的mysql驅動):
連接數據庫
- 安裝PyMySQL
- 修改配置文件
在工程目錄中init.py中寫入:
import pymysql pymysql.install_as_MySQLdb()
連接設置將被用在這些命令上:
- OPTIONS
- NAME,USER,PASSWORD,HOST,PORT
- MySQL選項文件。
換句話說,如果你設置數據庫的名稱在OPTIONS, 這將優先于NAME, 這將覆蓋任何在MySQL option file中的東西.
下面是使用一個MySQL選擇文件一個示例配置:
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/path/to/my.cnf',
},
}
}
# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8
其他幾個MySQLdb連接選項可能是有用的,例如ssl, init_command, and sql_mode. 查閱 MySQLdb documentation了解更多細節。
初始化數據庫
> python manage.py migrate
ORM機制簡介
ORM是什么?:(在django中,根據代碼中的類自動生成數據庫的表也叫–code first)
ORM:Object Relational Mapping(對象關系映射)
類名對應——》數據庫中的表名
類屬性對應———》數據庫里的字段
類實例對應———》數據庫表里的一行數據
obj.id obj.name…..類實例對象的屬性
調用sql語句
# views.py
from django.shortcuts import render
from django.contrib.auth.models import User
from django.http import HttpRequest,HttpResponse
# Create your views here.
def hello(request,a):
user_list = User.objects.all()
print(user_list.query)
return render(request,"table.html ",{'user_list':user_list})
直接在屏幕上顯示執行的sql語句
# 在project的setings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
常用操作
'''準備環境'''
D:\pythonwork\django\mysite>python manage.py shell
>>> from hello.models import *
插入數據
create和save方法
objects:model默認管理器,create是管理器的方法,save是model對象的方法。
插入主外鍵關系的時候,可以用對象的方式,也可以直接關聯ID的方式
插入多對多關系的時候要分步操作。
插入一個作者:
'''創建一個作者'''
>>> Author.objects.create(name='tom')
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.052) INSERT INTO `hello_author` (`name`) VALUES ('tom'); args=['tom']
<Author: Author object>
>>>
插入一個作者的詳細記錄:
>>> AuthorDetail.objects.create(sex=0,email='[email protected]',address='北京市海淀區梧桐路25號',birthday='19920202',author_id=1)
插入一個出版社的記錄
>>> pub = Publisher()
>>> pub.name = "中國電子出版社"
>>> pub.address = "北京市"
>>> pub.city = "北京市"
>>> pub.state_province = '北京市'
>>> pub.country = '中國'
>>> pub.website = 'http://www.miner-k.com'
>>> pub.save()
(0.052) INSERT INTO `hello_publisher` (`name`, `address`, `city`, `state_provinc
e`, `country`, `website`) VALUES ('中國電子出版社', '北京市', '北京市', '北京市'
, '中國', 'http://www.miner-k.com'); args=['中國電子出版社', '北京市', '北京市',
'北京市', '中國', 'http://www.miner-k.com']
插入一本書的記錄
>>> Book.objects.create(title='python入門到精通',publisher=pub,publisher_date='2012-12-12')
(0.067) INSERT INTO `hello_book` (`title`, `publisher_id`, `publisher_date`) VALUES ('python入門到精通', 1, '2012-12-12'); args=['python入門到精通', 1, '2012-12-12']
<Book: Book object>
插入書、作者、出版商關系的記錄
>>> book = Book.objects.get(id=1)
(0.002) SELECT VERSION(); args=None
(0.002) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_id`, `hello_book`.`publisher_date` FROM `hello_book` WHERE `hello_book`.`id` = 1; args=(1,)
>>> author = Author.objects.get(id=1)
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` WHERE `hello_author`.`id` = 1; args=(1,)
>>> book.authors.add(author)
(0.004) SELECT `hello_book_authors`.`author_id` FROM `hello_book_authors` WHERE
(`hello_book_authors`.`book_id` = 1 AND `hello_book_authors`.`author_id` IN (1)); args=(1, 1)
(0.066) INSERT INTO `hello_book_authors` (`book_id`, `author_id`) VALUES (1, 1); args=(1, 1)
>>>
修改數據
update和save方法
updete是QuerySet對象的方法
>>> author = Author.objects.get(id=1)
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` WHERE `hello_author`.`id` = 1; args=(1,)
>>> author.name = 'jim'
>>> author.save()
(0.586) UPDATE `hello_author` SET `name` = 'jim' WHERE `hello_author`.`id` = 1;args=('jim', 1)
查詢數據(惰性查詢)
所謂的惰性查詢:publisher.objects.all()只是返回一個QuarySet(查詢結果集對象),并不會馬上執行sql,而是當調用QuerySet的時候才會執行。
>>> Author.objects.all()
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` LIMIT 21; args=()
<QuerySet [<Author: Author object>]>
>>> Book.objects.all()
(0.002) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_id`, `hello_book`.`publisher_date` FROM `hello_book` LIMIT 21; args=()
<QuerySet [<Book: Book object>]>
刪除
delete方法
刪除id為1的書籍
'''刪除指定id的書籍'''
>>> Book.objects.filter(id=1).delete()
(0.003) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_
id`, `hello_book`.`publisher_date` FROM `hello_book` WHERE `hello_book`.`id` = 1; args=(1,)
(0.069) DELETE FROM `hello_book_authors` WHERE `hello_book_authors`.`book_id` IN (1); args=(1,)
(0.001) DELETE FROM `hello_book` WHERE `hello_book`.`id` IN (1); args=(1,)
(2, {'hello.Book': 1, 'hello.Book_authors': 1})
QuerySet常用的查詢相關的API
執行查詢的相關鏈接
QuerySet特點:
1.可迭代的
2.可切片的
# python manage.py shell
'''將查詢的結果存儲到一個變量中,通過查看變量的類型發現返回值是QuerySet類。 '''
>>> from hello.models import *
>>> pub_list = Publisher.objects.all()
>>> type(pub_list)
<class 'django.db.models.query.QuerySet'>
>>> for pub in pub_list:
... print(pub.name)
...
中國電子出版社
通過get獲取一個單一的對象
filter() 始終給你一個查詢集,即使只有一個對象滿足查詢條件 —— 這種情況下,查詢集將只包含一個元素。
如果你知道只有一個對象滿足你的查詢,你可以使用管理器的get() 方法,它直接返回該對象:
通過all獲取所有的對象
獲取一個表中所有對象的最簡單的方式是全部獲取。可以使用管理器的all() 方法:
>>> pub_list = Publisher.objects.all()
all()方法返回包含數據庫中所有對象的一個查詢集。
通過過濾器獲取特定的對象
all()方法 返回了一個包含數據庫表中所有記錄查詢集 。但在通常情況下,你往往想要獲取的是完整數據集的一個子集。
要創建這樣一個子集,你需要在原始的的查詢集上增加一些過濾條件。兩個最普遍的途徑是:
filter(**kwargs)
返回一個新的查詢集 ,它包含滿足查詢參數的對象。
exclude(**kwargs)
返回一個新的查詢集 ,它包含不滿足查詢參數的對象。
查詢參數(上面函數定義中的**kwargs)需要滿足特定的格式,下面字段查詢一節中會提到。
舉個例子,要獲取年份為2006的所有文章的查詢集,可以使用filter()方法:
>>> Author_list = Author.objects.filter(id=1)
返回第一個、最后一條結果
first()
返回結果集的第一個對象, 當沒有找到時返回None.如果 QuerySet 沒有設置排序,則將會自動按主鍵進行排序
例:
>>> Author.objects.all()
>>> Author.objects.all().first()
last()
工作方式類似first(),只是返回的是查詢集中最后一個對象。
顯示指定字段的值
values(*fields)
返回一個ValuesQuerySet —— QuerySet 的一個子類,迭代時返回字典而不是模型實例對象。而是一個可迭代的字典序列。
values_list
它與values()非常相似,只不過后者返回的結果是字典序列,而values_list()返回的是元組序列。
>>> Book.objects.filter(id=1).values('title','publisher_date')
<QuerySet [{'title': '巖石力學', 'publisher_date': datetime.date(2017, 11, 7)}]>
>>> Book.objects.filter(id=1).values_list('title','publisher_date')
<QuerySet [('巖石力學', datetime.date(2017, 11, 7))]>
QuerySet API參考
實例(單表查詢)
查詢id為1的書籍,并只顯示數據名稱和出版日期
>>> Book.objects.filter(id=1).values('title','publisher_date') <QuerySet [{'title': '巖石力學', 'publisher_date': datetime.date(2017, 11, 7)}]> >>> Book.objects.filter(id=1).values_list('title','publisher_date') <QuerySet [('巖石力學', datetime.date(2017, 11, 7))]>
查詢所有的出版社信息,并按照id降序排列,并嘗試使用reverse方法進行反向排序。
>>> Publisher.objects.all().order_by('id').values('name') <QuerySet [{'name': '中國電子出版社'}, {'name': '中國工業出版社'}, {'name': '山 西教育出版社'}]> >>> Publisher.objects.all().order_by('-id').values('name') <QuerySet [{'name': '山西教育出版社'}, {'name': '中國工業出版社'}, {'name': '中 國電子出版社'}]> >>> Publisher.objects.all().order_by('id').values('name').reverse() <QuerySet [{'name': '山西教育出版社'}, {'name': '中國工業出版社'}, {'name': '中 國電子出版社'}]>
顯示所有的出版社的地址,不能重復
>>> Publisher.objects.all().values('city') <QuerySet [{'city': '北京市'}, {'city': '天津市'}, {'city': '太原市'}, {'city': '太原市'}, {'city': '北京市'}, {'city': '北京市'}]> >>> Publisher.objects.all().values('city').distinct() <QuerySet [{'city': '北京市'}, {'city': '天津市'}, {'city': '太原市'}]>
查詢北京市的出版社
>>> Publisher.objects.filter(city='北京市').values('name') (0.002) SELECT `hello_publisher`.`name` FROM `hello_publisher` WHERE `hello_publ isher`.`city` = '北京市' LIMIT 21; args=('北京市',) <QuerySet [{'name': '中國電子出版社'}, {'name': '清華大學出版社'}, {'name': '北 大教育出版社'}]>
查詢北京市除外的出版社
>>> Publisher.objects.exclude(city='北京市').values('name') <QuerySet [{'name': '中國工業出版社'}, {'name': '山西教育出版社'}, {'name': '山 西大學出版社'}]>
查詢男作者的數量
>>> AuthorDetail.objects.filter(sex='男').count() (0.638) SELECT COUNT(*) AS `__count` FROM hello_authordetail` WHERE `hello_auth ordetail`.`sex` = '男'; args=('男',) 3
實例(多表查詢)
多表查詢的技巧:
__ : 兩個下劃線可以生成連接查詢,查詢關聯的字段信息
_set:提供了對象訪問相關聯表數據的方法,但是這種方式只能是相關類訪問定義了關系的類(主鍵類訪問外鍵類)
Publisher 類是Book類的主鍵類,
'''此處獲取Publisher對象只能通過get方法獲取,不能使用filter()'''
>>> pub_list = Publisher.objects.get(name='中國工業出版社')
>>> pub_list.book_set.all()
<QuerySet [<Book: Book object>]>
>>> pub_list.book_set.all().values('title')
<QuerySet [{'title': '流體力學'}]>
查詢客戶的完整信息
'''AuthorDetail中的屬性author是與表Author關聯,如果直接打印author屬性,打印的是author_id.如果需要打印Author的屬性name,需要打印變量author__name''' >>> from hello.models import * >>> AuthorDetail.objects.values('sex','email','address','birthday','author') <QuerySet [{'address': '北京市海淀區梧桐路25號', 'birthday': '19920202', 'author': 1, 'sex': '男', 'email': '[email protected]'}, {'address': '上海市外灘32號', 'bir thday': '19921201', 'author': 2, 'sex': '男', 'email': '[email protected]'}, {'address': '廣州市廣陵大道21號', 'birthday': '19981232', 'author': 3, 'sex': '女', 'email': '[email protected]'}, {'address': '深圳市為民道11號', 'birthday': '19990303', 'author': 4, 'sex': '男', 'email': '[email protected]'}]> >>> AuthorDetail.objects.values('sex','email','address','birthday','author__name') <QuerySet [{'address': '北京市海淀區梧桐路25號', 'birthday': '19920202', 'author__name': 'jim', 'sex': '男', 'email': '[email protected]'}, {'address': '上海市外灘32號', 'birthday': '19921201', 'author__name': 'jim', 'sex': '男', 'email': '[email protected]'}, {'address': '廣州市廣陵大道21號', 'birthday': '19981232', 'author__name': 'lucy', 'sex': '女', 'email': '[email protected]'}, {'address': '深圳市為民道11號', 'birthday': '19990303', 'author__name': 'jick', 'sex': '男', 'email': '[email protected]'}]>
查詢一本數書的作者姓名、出版社的名字
>>> Book.objects.filter(title='巖石力學').values('title','authors','publisher') <QuerySet [{'publisher': 1, 'authors': 1, 'title': '巖石力學'}]> >>> Book.objects.filter(title='巖石力學').values('title','authors__name','publisher__name') <QuerySet [{'publisher__name': '中國電子出版社', 'title': '巖石力學', 'authors__name': 'jim'}]>
查詢一個作者寫的所有的書籍
>>> Book.objects.filter(authors__name='jim').values('title') <QuerySet [{'title': '巖石力學'}]>
實例(聚合和分組查詢)
聚合查詢
aggrate通過QuerySet進行計算,返回一個聚合值的字典,aggregate()每一個參數都指定一個包含在字典中的返回值。
查詢某一個出版社出版書的數量
利用QuerySet的API
>>> from hello.models import * >>> Publisher.objects.filter(name='中國工業出版社').count() 1
利用聚合查詢aggregate
'''導入涉及到的模塊''' >>> from django.db.models import * >>> Publisher.objects.filter(name='中國工業出版社').aggregate(Count('name')) {'name__count': 1}
查詢某一個作者出版書籍的總價
>>> Book.objects.filter(authors__name='jim').aggregate(Sum('price')) {'price__sum': Decimal('10.00')}
分組查詢annotate
可以為QuerySet中的每一個對象添加注解,可以通過計算機查詢的結果中的每一個對象所關聯的對象集合,從而得出總計價(也可是平均值或總和等)
查詢所有的作者對應的所有出書的價格
>>> Book.objects.values('authors__name').annotate(Sum('price')) <QuerySet [{'authors__name': 'jim', 'price__sum': Decimal('10.00')}, {'authors__ name': 'lucy', 'price__sum': Decimal('10.00')}, {'authors__name': 'jick', 'price __sum': Decimal('10.00')}]>
查詢所有出版社最便宜書籍的價格
>>> Book.objects.values('publisher__name').annotate(Min('price')) <QuerySet [{'price__min': Decimal('10.00'), 'publisher__name': '中國電子出版社'} , {'price__min': Decimal('10.00'), 'publisher__name': '中國工業出版社'}, {'price __min': Decimal('10.00'), 'publisher__name': '山西教育出版社'}]>
數據模型
一對一:
作者模型:一個作者有姓名(一對一)
作者詳情模型:作者的詳情中有,性別、email地址、和出生日期、作者詳情模型和作者模型之間是一對一的關系
一對多:
出版商模型:出版商有名稱、地址、所在城市、省、國家、網站。
書籍模型:書籍有書名和出版商。一本書可以有多個作者,一個作者可以有多本書,所以作者和書籍的關系是多對多的關系【many-to-many】。一本書只能是一個出版商出版,一個出版商可以出版多本書,出版商和書籍是一對多的關系【one-to-many】,也被稱為外鍵【foreignkey】
修改配置文件
# models.py
from django.db import models
# Create your models here.
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Author(models.Model):
name = models.CharField(max_length=30)
class AuthorDetail(models.Model):
sex = models.CharField(max_length=1,choices=((0,'男'),(1,'女')))
email = models.CharField()
address = models.CharField(max_length=50)
birthday = models.CharField()
author = models.OneToOneField(Author)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publisher_date = models.DateField()
代碼簡介:
- 每個數據模型類型都是Django.db.models.Models的子類。它的的父類Model中包含了所有必要的和數據庫交互的方法,并提供了一個簡潔漂亮的定義數據庫字段的語法。
- 每個模型相當于單個數據庫表(這條規則的例外情況是多對多的關系,多對多關系的時候會多生出一張表關系),每個屬性也是這個表的一個字段,屬性名是字段名,它的類型(例如CharField)相當于數據庫的字段類型(例如varchar)。
- 模型之間的關系:一對一(OneToOneField),一對多(ForeignKey)和多對多(ManyToManyField)
生成數據庫同步腳本
> python manage.py makemigrations
同步數據庫
> python manage.py migrate
查看數據庫的變化
同步數據庫之前:
同步數據庫之后:
新增加的表就是在models.py中的class。表名就是庫名,表中的字段就是類的屬性。
常用的字段類型:
字段類型 | 含義 |
---|---|
AutoField | 一個根據實際ID自動增長的IntegerField |
BigIntegerField | 一個64位整數, 類似于一個 IntegerField |
BinaryField | 二進制類型 |
BooleanField | 布爾字段類型 |
CharField | 字符串類型 |
DateField | 日期字段 |
DateTimeField | 日期時間字段 |
DecimalField | 精確小數字段 |
EmailField | email字段類型 |
FileField | 文件字段類型 |
FloatField | 浮點數字段類型 |
ImageField | 圖片字段類型 |
IntegerField | 整數字段類型 |
IPAddressField | IP字段類型 |
SmallIntegerField | 小整型字段類型 |
TextField | 文本字段類型 |
URLField | url字段類型 |
字段選項
字段選項名稱 | 含義 |
---|---|
null | 如果為True,Django將在數據庫中將空值存儲為NULL。默認值是 False |
blank | 如果為True,則該字段允許為空白。 默認值是 False |
choices | 它是一個可迭代的結構(比如,列表或是元組),由可迭代的二元組組成(比如[(A, B), (A, B) …]),用來給這個字段提供選擇項。 |
default | 該字段的默認值 |
help_text | 額外的 ‘help’ 文本將被顯示在表單控件form中 |
primary_key | 若為 True, 則該字段會成為模型的主鍵字段 |
unique | 如果為 True, 這個字段在表中必須有唯一值 |
數據庫同步
'''如果數據庫中字段增加或修改,需啊喲重新同步數據庫'''
D:\pythonwork\django\mysite>python manage.py makemigrations
You are trying to add a non-nullable field 'price' to book without a default; we
can''t do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null
value for this column)
'''第二點中提示退出設置增加字段的默認值,在增加的字段中添加參數default='''
2) Quit, and let me add a default in models.py
Select an option: 2
D:\pythonwork\django\mysite>python35 manage.py makemigration
D:\pythonwork\django\mysite>python35 manage.py migrate
認識一個目錄
目錄名:migrations
作用:用來存放通過makemirgrations命令生成的數據庫腳本。app目錄下面必須要有migrations的目錄且該目錄下必須存放__init__.py
才能正常的使用數據庫的同步功能。
認識一張表(django_migrations)
記錄migrantions目錄下腳本的使用情況
和數據庫相關的命令
flush:清空數據庫,恢復數據庫到最初的狀態
makemigrantions:生成數據同步的腳本
migrate:同步數據庫
showmigrations:查看生成的數據庫同步腳本
sqlflush:查看生成清空數據庫的腳本
sqlmigrate:查看數據庫同步的sql語句
使用原生的sql
使用原生sql的方式主要的目的是解決一些復雜的sql不能用ORM的方式寫出的問題。
extra:結果集修改器,一種提供額外查詢參數的機制
raw:執行原始sql并返回模式實例
直接自定義SQL(這種方式不依賴于model,前兩種方式要依賴于model)
extra實例
查詢山西教育出版社出版所有價格大于10元的圖書
>>> Book.objects.filter(publisher__name='山西教育出版社').extra(where=['price>10']).values('title') <QuerySet [{'title': '材料力學'}, {'title': '工程力學'}]>
等價于
>>> Book.objects.filter(publisher__name='山西教育出版社',price__gt=10).values('title') <QuerySet [{'title': '材料力學'}, {'title': '工程力學'}]>
使用raw
>>> Book.objects.raw('select * from hello_book')
<RawQuerySet: select * from hello_book>
>>> book_list = Book.objects.raw('select * from hello_book')
>>> for book in book_list:
... print(book.title)
...
(0.003) select * from hello_book; args=()
巖石力學
流體力學
材料力學
工程力學
使用自定sql語句
>>> from django.db import connection
>>> cursor = connection.cursor()
'''插入數據'''
>>> cursor.execute('insert into hello_author(name) values("郭敬明")')
(0.087) insert into hello_author(name) values("郭敬明"); args=None
1
'''修改數據'''
>>> cursor.execute('update hello_author set name="韓寒" where name="郭敬明"')
(0.071) update hello_author set name="韓寒" where name="郭敬明"; args=None
1
'''刪除數據'''
>>> cursor.execute('delete from hello_author where name="韓寒"')
(0.205) delete from hello_author where name="韓寒"; args=None
1
'''查詢語句'''
>>> cursor.execute('select * from hello_author')
(0.002) select * from hello_author; args=None
4
'''獲取數據'''
>>> raw = cursor.fetchone()
>>> cursor.fetchone()
(2, 'jim')
>>> cursor.fetchone()
(3, 'lucy')
>>> cursor.fetchone()
(4, 'jick')
>>> cursor.fetchone()
模板
常用標簽
autoescape控制自動轉義
控制自動轉義是否可用.這種標簽帶有任何 on 或 off 作為參數的話,他將決定轉義塊內效果。該標簽會以一個endautoescape作為結束標簽.
當自動轉義生效時,所有變量內容會被轉義成HTML輸出(在所有過濾器生效后)這等同與手動將escape篩選器應用于每個變量。
唯一一個例外是,變量或者通過渲染變量的代碼,或者因為它已經應用了 safe或escape過濾器,已經被標記為“safe”。
例如:
在views.py中
def test(request):
value3 = "<a href=''>百度</a>"
return render(request,'test.html',locals())
在test.html中
{% autoescape on %}
{{ values4 }}
{% endautoescape %}
if 標簽的使用
格式:
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
實例:
#views.py
def test(request):
number1 = 20
return render(request,'test.html',locals())
#test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test-Title</title>
</head>
<body>
{% if number1 == 10 %}
NUM:10
{% elif number1 == 20 %}
NUM:20
{% else %}
unknow
{% endif %}
</body>
</html>
#mysite/urls.py
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('hello.urls')),
]
#hello/urls.py
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
url(r'^test/$', views.test),
]
訪問測試:http://127.0.0.1:8000/test/
for標簽的設置
#views.py
def test(request):
number1 = 20
num_list = [1,2,3,4,5,6,7,8]
return render(request,'test.html',locals())
#test.html
<ul>
{% for num1 in num_list %}
<li>{{ num1 }}</li>
{% endfor %}
</ul>
訪問測試:http://127.0.0.1:8000/test/
verbatim標簽
停止模板引擎在該標簽的中渲染
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
filter標簽
將字符全部小寫
{% filter force_escape|lower %}
This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}
全部轉化為大寫
{% filter force_escape|upper %}
This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}
內置過濾器
add
把add后的參數加給value
例如:
{{ value|add:"2" }}
如果 value 為 4,則會輸出 6.
過濾器首先會強制把兩個值轉換成Int類型。如果強制轉換失敗, 它會試圖使用各種方式吧兩個值相加。它會使用一些數據類型 (字符串, 列表, 等等.) 其他類型則會失敗. Day of the month, 2 digits with leading zeros.
例如:,我們使用下面的值
{{ first|add:second }}
first 是 [1, 2, 3] ,second 是 [4, 5, 6], 將會輸出 [1, 2, 3, 4, 5, 6].
警告:
如果字符串可以被強制轉換成int類型則會 summed,無法被轉換,則和上面的第一個例子一樣
addslashes在引號前面加上斜
例如,用于在CSV中轉義字符串。
例如:
在views.py中
def test(request):
number1 = 20
num_list = [1,2,3,4,5,6,7,8]
value = datetime.datetime.now()
value1 = "I'm a boy"
return render(request,'test.html',locals())
在test.html中
{{ value1|addslashes }}
如果value 是 “I’m using Django”, 輸出將變成 “I\’m using Django”.
date
例如:
{{ value|date:"D d M Y" }}
如果value是datetime對象(例如,datetime.datetime.now()的結果),輸出將是字符串 ‘Wed 09 Jan 2008’
default
如果value的計算結果為False,則使用給定的默認值。否則,使用該value。
例如:
在views.py中
def test(request):
value2 = ""
return render(request,'test.html',locals())
在test.html中
{{ value2|default:"nothing" }}
如果value為”“(空字符串),則輸出將為nothing。
default_if_none
如果(且僅當)value為None,則使用給定的默認值。否則,使用該value。
注意,如果給出一個空字符串,默認值將不被使用。如果要回退空字符串,請使用default過濾器。
例如:
{{ value|default_if_none:"nothing" }}
如果value為None,則輸出將為字符串“nothing”
escape 轉義字符串
轉義字符串的HTML。具體來說,它使這些替換:
<轉換為<
>轉換為>
'(單引號)轉換為'
"(雙引號)轉換為"
&轉換為&
轉義僅在字符串輸出時應用,因此在連接的過濾器序列中escape的位置無關緊要:它將始終應用,就像它是最后一個過濾器。如果要立即應用轉義,請使用force_escape過濾器。
將轉義應用于通常會對結果應用自動轉義的變量只會導致一輪轉義完成。因此,即使在自動逃逸環境中使用此功能也是安全的。如果要應用多個轉義通過,請使用force_escape過濾器。
例如,您可以在autoescape關閉時將escape應用于字段:
{% autoescape off %}
{{ title|escape }}
{% endautoescape %}
filesizeformat 格式化文件大小
格式化數值為“人類可讀”的文件大小(例如’13 KB’, ‘4.1 MB’, ‘102 bytes’等)。
例如:
{{ value|filesizeformat }}
first 返回列表中的第一個值
返回列表中的第一項。
例如:
{{ value|first }}
last 返回列表中的最后一個值
返回列表中的最后一個項目。
例如:
{{ value|last }}
safe 字符串不轉義
將字符串標記為在輸出之前不需要進一步的HTML轉義。當自動轉義關閉時,此過濾器不起作用。
注意:如果您要鏈接過濾器,在safe后應用的過濾器可能會使內容再次不安全。例如,以下代碼按原樣打印變量:
{{ var|safe|escape }}
truncatechars 截取指定個數的字符串
如果字符串字符多于指定的字符數量,那么會被截斷。截斷的字符串將以可翻譯的省略號序列(“…”)結尾。
參數:要截斷的字符數
例如:
{{ value|truncatechars:5 }}
如果value是“Joel is a >,輸出將為“Joel i …”。
如果value是”123456789”,輸出結果為“12…”。輸出的總共的字符串格式是5,包含三個省略號。
truncatewords 截取指定個數的單詞
在一定數量的字后截斷字符串。
參數:要截斷的字數
例如:
{{ value|truncatewords:2 }}
如果value 是 “Joel is a slug”, 輸出變為 “Joel is …”.
striptags
盡一切可能努力剝離所有[X] HTML標簽。
例如:
{{ value|striptags }}
如果 value 的值是 “Joel is a slug“, 輸出的結果是”Joel is a slug”.
無安全保證
請注意,striptags不會保證其輸出是HTML安全的,尤其是對于無效的HTML輸入。因此,NEVER將safe過濾器應用于striptags輸出。如果您正在尋找更強大的功能,可以使用bleach Python庫,特別是其clean方法。
模板的繼承
include標簽
在模板的存放位置有sub.html和table.html兩個模板
在sub.html中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 這是一個子模板 </body> </html>
table.html在body中增加下面一行
...... <br> {% include 'sub.html' %}
訪問指定的頁面會看到子模板中的內容。如果子模板在table.html同級目錄下的dir1中,此處應該寫
<br> {% include 'dir1\sub.html' %}
傳遞變量到子模板中
table.html在body中增加下面一行
<br> {% include "dir1/sub.html" with person="Jane" greeting="Hello" %}
sub.html在body中增加變量
<body> 這是一個子模板{{person}} </body>
block標簽
views.py中增加
def test1(request):
return render(request,'test1.html',locals())
在hello/urls.py中設置
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
url(r'^test/$', views.test),
url(r'^testbase/$', views.test1),
]
base.html中
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}我的基礎模板{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
test1.html中(base.html的子模板版)
{% extends "base.html" %}/span>
{% block title %}這是我的第I個子模板{% endblock %}
{% block content %}
這是子模板的內容
{% endblock %}
admin的后臺管理
兩種注冊方法
注冊方法
ModelAdmin objects
ModelAdmin類是模型在Admin 界面中的表示形式。通常,將它們在你的應用中的名為admin.py的文件里
from django.contrib import admin
from myproject.myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
如果對于默認的Admin 界面足夠滿意,那你根本不需要自己定義ModelAdmin 對象, 你可以直接注冊模型類而無需提供ModelAdmin 的描述
from django.contrib import admin
from myproject.myapp.models import Author
admin.site.register(Author)
實例
在文件hello/admin.py中,
class PublisherAdmin(admin.ModelAdmin):
list_display = ('name','address','city','state_province','country','website',)
admin.site.register(Author)
admin.site.register(Publisher,PublisherAdmin)
admin.site.register(AuthorDetail)
admin.site.register(Book)
注冊裝飾器
@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
list_display = ('name','address','city','state_province','country','website',)
admin.site.register(Author)
# admin.site.register(Publisher,PublisherAdmin)
admin.site.register(AuthorDetail)
admin.site.register(Book)
ModelAdmin 選項
list_display顯示指定的字段
使用list_display 去控制哪些字段會顯示在Admin 的修改列表頁面中。
list_display = ('name','address','city','state_province','country','website',)
search_fields指定搜索的字段
search_fields = ('name','address')
list_filter指定列表過濾器
list_filter = ('state_province',)
ordering排序
ordering = ('name',)
如果界面上有name字段,會在子段的旁邊顯示上下箭頭(選擇升序或者降序)
編輯表單 fields/exclude
只能編輯的表單
fields = ('name','address')
除了指定的字段之外的表單都能編輯
exclude = ('name','address')
fieldsets
界面顯示:
fieldsets = (
(None, {
'fields': ('name', 'address', )
}),
('Advanced options', {
'classes': ('collapse',),
'fields': ('city', 'state_province', 'country')
}),
)
使用表單 form
django表單系統中,所有的表單類都是作為django.forms.form的子類創建的。包括ModelForm
關于表單系統主要分為兩類,
基于django.forms.Form:所有表單類的父類
基于django.forms.ModelForm: 可以和模型類綁定的Form
不使用From的情況配置,添加出版社信息
/hello/urls.py
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
url(r'^test/$', views.test),
url(r'^testbase/$', views.test1),
url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),
]
hello/views.py中增加函數
from hello.models import Publisher
.......
def add_publisher(request):
if request.method == 'POST':
# 如果是POST提交,去接受用戶提交的數據
name = request.POST.get('name')
address = request.POST.get('address')
city = request.POST.get('city')
state_province = request.POST.get('state_province')
country = request.POST.get('country')
website = request.POST.get('website')
Publisher.objects.create(
name = name,
address = address,
city = city,
state_province = state_province,
country = country,
website = website,
)
return HttpResponse("添加出版社成功")
else:
# 否則將傳輸的數據打印
return render(request,'add_publisher.html',locals())
templates目錄下增加add_publisher.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加出版社信息</title>
</head>
<body>
<form action="{% url 'add_publisher' %}" method="post" >
{% csrf_token %}
名稱:<input type="text" name="name"><br>
地址:<input type="text" name="address"><br>
城市:<input type="text" name="city"><br>
省份:<input type="text" name="state_province"><br>
國家:<input type="text" name="country"><br>
網站:<input type="text" name="website"><br>
<input type="submit",name="提交"><br>
</form>
</body>
</html>
使用Django_Form
/hello/urls.py
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
url(r'^test/$', views.test),
url(r'^testbase/$', views.test1),
url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),
]
hello/forms.py
from django import forms
class PublisherForm(forms.Form):
# label標簽代表的是在界面上顯示的信息,默認情況下顯示的英文
name = forms.CharField(label='姓名')
address = forms.CharField(label='地址')
city = forms.CharField(label='城市')
state_province = forms.CharField(label='省份')
country = forms.CharField(label='國家')
website = forms.URLField(label='網站')
hello\view.py
from hello.forms import PublisherForm
from hello.models import Publisher
def add_publisher(request):
if request.method == 'POST':
# 如果是POST提交,去接受用戶提交的數據
# 使用Django_form
publisher_form = PublisherForm(request.POST)
if publisher_form.is_valid():
Publisher.objects.create(
name = publisher_form.cleaned_data['name'],
address = publisher_form.cleaned_data['address'],
city = publisher_form.cleaned_data['city'],
state_province = publisher_form.cleaned_data['state_province'],
country = publisher_form.cleaned_data['country'],
website = publisher_form.cleaned_data['website'],
)
return HttpResponse("添加出版社成功")
else:
# 否則將傳輸的數據打印
publisher_form = PublisherForm()
return render(request,'add_publisher.html',locals())
templates目錄下增加add_publisher.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加出版社信息</title>
</head>
<body>
<form action="{% url 'add_publisher' %}" method="post" >
{% csrf_token %}
{{ publisher_form.as_p }} // 將view.py中創建的表單對象傳輸到模版中,表單中的字段會自動生成,as_p表示的是輸出的格式使用</p>標簽
<input type="submit" name="提交"><br>
</form>
</body>
</html>
使用ModelForm
/hello/urls.py
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/$', views.hello,{'a':123}),
url(r'^test/$', views.test),
url(r'^testbase/$', views.test1),
url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),
]
hello/forms.py
from django import forms
from hello.models import Publisher
class PublisherForm(forms.ModelForm):
class Meta:
model = Publisher
exclude = ("id",)
hello\view.py
from hello.forms import PublisherForm
from hello.models import Publisher
def add_publisher(request):
if request.method == 'POST':
# 如果是POST提交,去接受用戶提交的數據
# 使用Django ModelForm
publisher_form = PublisherForm(request.POST)
if publisher_form.is_valid():
publisher_form.save()
return HttpResponse("添加出版社成功")
else:
# 否則將傳輸的數據打印
publisher_form = PublisherForm()
return render(request,'add_publisher.html',locals())
templates目錄下增加add_publisher.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加出版社信息</title>
</head>
<body>
<form action="{% url 'add_publisher' %}" method="post" >
{% csrf_token %}
{{ publisher_form.as_p }} // 將view.py中創建的表單對象傳輸到模版中,表單中的字段會自動生成,as_p表示的是輸出的格式使用</p>標簽
<input type="submit" name="提交"><br>
</form>
</body>
</html>
參考文檔
智能推薦
openstack開發實踐(二):Django框架簡介和Django應用的編寫
Django框架簡介 Django是Python最有代表性的一個網絡框架。使用Django可以方便地實現一個功能全面、管理簡便的網站或者APP后端。openstack中用來提供圖形化界面服務的Dashboard就是利用Django框架進行開發,所以在介紹openstack dashboard開發之前,通過本篇文章針對Django應用開發進行講解。 Django的MTV(模型-模板-視圖)模式本質上...
Django 系列1:Django簡介
1、Django MTV框架 MVC MTV 2、安裝 虛擬環境 pip install Django==2.2.9 3、創建工程 django-admin startproject HelloDjango python mange.py startapp App er python mange.py runserver Django自帶內置了一個開發者服務器,性能比較低,上線以后不能用runse...
【Django】簡介和 hello Django
Django 簡介 Django 最初發布在 2005 年,是當前 python 比較成熟且知名的網絡框架,最初被用來制作 新聞站點django 的官方網站:https://www.djangoproject.com/;django 采用的是 MVC 的框架模式,因為一個Django 項目由 models view 和 templates 組成,所以也被叫做 MVT 的設計模式 MVC 設計模式 ...
Django框架
一、Django建站基礎 1. Django項目創建 step1. 創建工程 ● manage.py : 命令行工具,允許以多種方式與項目進行交互。在CMD窗口下,將路徑切換到django項目下輸入 python manage.py help 可以查看工具的具體功能 ● init.py : 初始化文件,通常無需修改 ● setting.py : 項目配置文件 ● url.py : 項目的URL設置...
Django框架
一、什么是web框架 框架,即framework,特指為解決一個開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來做表演。 對于所有的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。 最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,...
猜你喜歡
Django框架
電商網站(Django框架)—— 大綱內容與基本功能分析 原創 2017年10月28日 14:42:20 1323 1. 項目架構 2. 數據庫表結構 3. 數據庫讀寫分離 4. Django讀寫分離配置 新建utils/db_router.py 課后閱讀資料 ...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...