Python Web框架——Django

返回頂部php

使用框架簡單快速開發特定的系統。html



pip freeze > requirements.txt
pip install -r requirements.txt

一 MVC和MTV模式

 

二 簡介

Django時有Python開發的一個免費的開源網站框架,能夠用於快速搭建高性能、優雅的網站。java

Django框架的特色:python

  • 強大的數據庫功能
  • 自帶強大的後臺功能
  • 經過正則匹配隨意定義的網址
  • 強大易擴展的模板系統
  • 緩存系統
  • 國際化

三 Django安裝方式

1.利用pip安裝Django。mysql

oliver@oliver-G460:~$ sudo pip3 install Django

2.利用源碼包安裝Django。linux

oliver@oliver-G460:~$ tar -zxvf django-1.10.xx.tar.gz

 解壓後進入目錄,執行:git

python3 setup.py install

3.利用Linux自帶源安裝Django。web

sudo apt-get install python3-django

 

檢查Django是否安裝成功:正則表達式

oliver@oliver-G460:~$ python3
Python 3.5.2 (default, Sep 10 2016, 08:21:44) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(1, 10, 2, 'final', 0)

 

 若是但願安裝不一樣版本的Django環境,則須要經過virtualenv來管理多個開發環境。sql

四 Django項目建立

方式一:用命令建立項目和app

1. 建立一個新的Django項目

2. 建立app

python3 manage.py startapp app-name 或 django-admin.py startapp app-name

須要注意的是,經過命令行建立的項目,在settings.py中,如app名稱和模板路徑及templates目錄等信息要本身添加。

方式二:用Pycharm建立

在File→New Project中選擇Django,輸入項目名稱mysite和應用名稱myApp,完成建立。

建立完成後, 用Pycharm打開項目,查看項目和app目錄文件

  • manage.py:用於管理Django站點。
  • settings.py:項目全部的配置信息,包含項目默認設置,數據庫信息,調試標識以及其它工做變量等。
  • urls.py:負責把URL映射到視圖函數,即路由系統。
  • wsgi.py:內置runserver命令的WSGI應用配置。

 五 Django urls(路由系統)

 即urls.py文件。其本質是創建url與其所調用的視圖函數的映射關係,以此來規定訪問什麼網址去對應什麼內容,執行哪一個視圖函數。

urlpatterns = [
        url(正則表達式,views視圖函數,[參數],[別名]),   
]

 說明(括號中四部分的意義):

  • 正則表達式字符串來匹配瀏覽器發送到服務端的URL網址
  • 可調用的視圖函數對象。先引入(import)再使用
  • 要傳給視圖函數的默認參數(字典形式)
  • name,即別名。HTML中form表單參數action屬性值使用此別名後,即使url發生變化,也無需在HTML中批量進行修改。

1 URL配置舉例:

from django.conf.urls import url
from django.contrib import admin

from app01 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})/$', views.year_archive),  #no_named group

    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),

]
View Code

用()括起來表示保存爲一個子組,每一個子組做爲一個參數(無名參數),被views.py中的對應函數接收。參數個數與視圖函數中的形參個數要保持一致。

 

(注意:當匹配到第一個url後當即返回,再也不向下查找匹配。)

2 帶命名的組Named group(?P<>)用法

?P<group_name> 表示帶命名的參數,例如:將year='2016'做爲一個總體傳個視圖函數。此處的組名稱必須與視圖函數中的形參名稱一致。因爲有參數名稱與之對應,因此視圖函數有多個形參時,不須要考慮參數的前後順序。

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),  # year=2016
    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),
]

3 默認參數(可選)

以下所示,若是請求地址爲/blog/2016,表示將year='2016',foo='bar'傳給視圖函數,視圖函數中必須有相同名稱的形參來接收值。

from django.conf.urls import url
from . import views
  
urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

4 name別名(可選)

 固定用法:

url(r'^/index/',views.index,name='bieming')

若是url中的路徑修改成/index2/,對應的模板,甚至還視圖中的跳轉,以及 models.py 中也可能有獲取網址的地方。每一個地方都要改,修改的代價很大,一不當心,有的地方沒改過來,那個就不能用了。

所以,在須要跳轉或獲取網址的地方,使用別名設置的名稱,之後即可以隨意修改url了。

urlpatterns = [
    url(r'^index',views.index,name='bieming'),
    url(r'^admin/', admin.site.urls),
    # 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),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登錄成功")



    return render(req,'index.html')

#####################

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'bieming' %}" method="post">
         用戶名:<input type="text" name="username">
         密碼:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


#######################
View Code

 5 URLconf

一個網站包含成千上萬個URL,若是全部的URL映射都放在一個文件下,極可能會出錯,也不便與維護。

所以,咱們在每一個app應用下分別建立一個urls目錄,將不一樣的請求分發給不一樣app下的urls去匹配,如:對於/blog/index/請求直接交給‘blog.urls’去處理,清晰明確,更方便管理。

 

六 Django views(視圖函數)

 http請求中產生的兩大核心對象:

http請求:HttpRequest對象

http響應:HttpResponse對象

所在位置:django.http

request就是指HttpRequest。

1 HttpRequest對象的屬性和方法

 

屬性  描述
path 請求頁面的全路徑,不包括域名—例如, "/music/bands/the_beatles/"。
method 請求中使用的HTTP方法的字符串表示。全大寫表示。
GET 包含全部HTTP GET參數的類字典對象
POST 包含全部HTTP POST參數的類字典對象
REQUEST 爲了方便,該屬性是POST和GET屬性的集合體,可是有特殊性,先查找POST屬性,而後再查找GET屬性
COOKIES 包含全部cookies的標準Python字典對象。Keys和values都是字符串。
FILES 包含全部上傳文件的類字典對象。FILES中的每一個Key都是<input type="file" name="" />標籤中name屬性的值. FILES中的每一個value 同時也是一個標準Python字典對象,包含下面三個Keys:(Filename: 上傳文件名,用Python字符串表示;content-type: 上傳文件的Content type;content: 上傳文件的原始內容)注意:只有在請求方法是POST,而且請求頁面中<form>enctype="multipart/form-data"屬性時FILES才擁有數據。不然,FILES 是一個空字典。
META 包含全部可用HTTP頭部信息的字典,例如:(CONTENT_LENGTH,CONTENT_TYPE,QUERY_STRING: 未解析的原始查詢字符,串,REMOTE_ADDR: 客戶端IP地址REMOTE_HOST: 客戶端主機名,SERVER_NAME: 服務器主機名,SERVER_PORT: 服務器端口);META 中這些頭加上前綴HTTP_最爲Key, 例如:(HTTP_ACCEPT_ENCODING,HTTP_ACCEPT_LANGUAGE,HTTP_HOST: 客戶發送的HTTP主機頭信息,HTTP_REFERER: referring頁,HTTP_USER_AGENT: 客戶端的user-agent字符串,HTTP_X_BENDER: X-Bender頭信息)
user 是一個django.contrib.auth.models.User 對象,表明當前登陸的用戶。若是訪問用戶當前沒有登陸,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。見例子1
session 惟一可讀寫的屬性,表明當前會話的字典對象。只有激活Django中的session支持時該屬性纔可用。
raw_post_data 原始HTTP POST數據,未解析過。 高級處理時會有用處。

 

method  描述
__getitem__(key) 返回GET/POST的鍵值,先取POST,後取GET。若是鍵不存在拋出 KeyError。這是咱們可使用字典語法訪問HttpRequest對象。例如:request["foo"]等同於先request.POST["foo"] 而後 request.GET["foo"]的操做。
has_key() 檢查request.GET or request.POST中是否包含參數指定的Key。
get_full_path() 返回包含查詢字符串的請求路徑。例如, "/music/bands/the_beatles/?print=true"
is_secure() 若是請求是安全的,返回True,就是說,發出的是HTTPS請求。
get_full_path(),   好比:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()獲得的結果就是/index33/?name=123
req.path獲得的結果是:/index33

2 HttpResponse對象的屬性和方法

 對於HttpRequest對象來講,是由django自動建立的,可是,HttpResponse對象就必須咱們本身建立。每一個view請求處理方法必須返回一個HttpResponse對象。

  HttpResponse類在django.http.HttpResponse

  在HttpResponse對象上擴展的經常使用方法:

頁面渲染:         render()(推薦)        或         render_to_response(),
頁面跳轉:         redirect("路徑")
locals():    能夠直接將函數中全部的變量傳給模板

七 Django templates(模板)

 模板由HTML+邏輯控制代碼組成。

1 變量

使用雙大括號來引用變量

語法格式:       {{var_name}}

2 Template和Context對象

渲染操做流程:

一旦建立Template對象以後,能夠用context傳遞數據給它,它是一系列變量和它們值的集合,模板使用它來賦值模板變量標籤和執行塊標籤

context在django裏表現爲Context類,在django.template模塊中

Context類構造是一個可選參數:一個字典映射變量和它們的值

建立一系列Context對象以後,調用Template對象的render()方法並傳遞Context對象來填充模板

同一個模板渲染多個context:

1 >>>from django,template import Template,Context
2 >>>t=Template("My name is {{name}},I love{{language}}")
3 >>>c=Context({'name':'BeginMan','language':'Python/Js/C#'})
4 >>>t.render(c)
5 --------------------------------output----------------------------------------------
6 My name is BeginMan ,I love Python/Js/C#


推薦寫法:

def current_time(req):

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {'current_date':now})    # 字典部分指定就是Context對象,render()方法將Context對象的鍵值傳遞給模板,並填充模板。

 3 深度變量查找

context不只能傳遞簡單的參數(字符串),也能夠傳遞列表和字典對象。

 1 #最好是用幾個例子來講明一下。
 2 # 首先,句點可用於訪問列表索引,例如:
 3 
 4 >>> from django.template import Template, Context
 5 >>> t = Template('Item 2 is {{ items.2 }}.')
 6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
 7 >>> t.render(c)
 8 'Item 2 is carrots.'
 9 
10 #假設你要向模板傳遞一個 Python 字典。 要經過字典鍵訪問該字典的值,可以使用一個句點:
11 >>> from django.template import Template, Context
12 >>> person = {'name': 'Sally', 'age': '43'}
13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
14 >>> c = Context({'person': person})
15 >>> t.render(c)
16 'Sally is 43 years old.'
17 
18 #一樣,也能夠經過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有
19 #year 、 month 和 day 幾個屬性,你一樣能夠在模板中使用句點來訪問這些屬性:
20 
21 >>> from django.template import Template, Context
22 >>> import datetime
23 >>> d = datetime.date(1993, 5, 2)
24 >>> d.year
25 >>> d.month
26 >>> d.day
27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
28 >>> c = Context({'date': d})
29 >>> t.render(c)
30 'The month is 5 and the year is 1993.'
31 
32 # 這個例子使用了一個自定義的類,演示了經過實例變量加一點(dots)來訪問它的屬性,這個方法適
33 # 用於任意的對象。
34 >>> from django.template import Template, Context
35 >>> class Person(object):
36 ...     def __init__(self, first_name, last_name):
37 ...         self.first_name, self.last_name = first_name, last_name
38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
39 >>> c = Context({'person': Person('John', 'Smith')})
40 >>> t.render(c)
41 'Hello, John Smith.'
42 
43 # 點語法也能夠用來引用對象的方法。 例如,每一個 Python 字符串都有 upper() 和 isdigit()
44 # 方法,你在模板中可使用一樣的句點語法來調用它們:
45 >>> from django.template import Template, Context
46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
47 >>> t.render(Context({'var': 'hello'}))
48 'hello -- HELLO -- False'
49 >>> t.render(Context({'var': '123'}))
50 '123 -- 123 -- True'
51 
52 # 注意這裏調用方法時並* 沒有* 使用圓括號 並且也沒法給該方法傳遞參數;你只能調用不需參數的
53 # 方法。
View Code

4 變量過濾器filter

語法格式:      {{obj|filter:param}}
 1 # 1  add          :   給變量加上相應的值
 2    #
 3    # 2  addslashes   :    給變量中的引號前加上斜線
 4    #
 5    # 3  capfirst     :    首字母大寫
 6    #
 7    # 4  cut          :   從字符串中移除指定的字符
 8    #
 9    # 5  date         :   格式化日期字符串
10    #
11    # 6  default      :   若是值是False,就替換成設置的默認值,不然就是用原本的值
12    #
13    # 7  default_if_none:  若是值是None,就替換成設置的默認值,不然就使用原本的值
14 
15 
16 #實例:
17 
18 #value1="aBcDe"
19 {{ value1|upper }}
20 
21 #value2=5
22 {{ value2|add:3 }}
23 
24 #value3='he  llo wo r ld'
25 {{ value3|cut:' ' }}
26 
27 #import datetime
28 #value4=datetime.datetime.now()
29 {{ value4|date:'Y-m-d' }}
30 
31 #value5=[]
32 {{ value5|default:'空的' }}
33 
34 #value6='<a href="#">跳轉</a>'
35 
36 {{ value6 }}
37 
38 {% autoescape off %}
39   {{ value6 }}
40 {% endautoescape %}
41 
42 {{ value6|safe }}
43 
44 {{ value6|striptags }}
45 
46 #value7='1234'
47 {{ value7|filesizeformat }}
48 {{ value7|first }}
49 {{ value7|length }}
50 {{ value7|slice:":-1" }}
51 
52 #value8='http://www.baidu.com/?a=1&b=3'
53 {{ value8|urlencode }}
54     value9='hello I am yuan'
View Code

5 經常使用標籤(tag)

語法格式:      {% tags %}

(1)  {% if %}

 

(2)  {% for %}

 

(3)  {% csrf_token %}

 

(4)  {% url %} :引用路由配置的地址

 

(5)  {% with %} :用簡短的變量名代替複雜的變量名

 

(6) {% verbatim %} :禁止render

 

(7) {% load %} :加載標籤庫

 

6 自定義filter和simple_tag

(1)在app下建立templatetags目錄或模塊,目錄名稱必須這樣寫。

(2)建立.py文件,如my_tags。(其中,register名稱不可改變)

(3)在使用自定義filter和simple_tag的html文件以前,經過 {% load my_tags %}導入前面本身建立的my_tags標籤庫。(注意:settings中INSTALLED_APPS中必須添加當前的app名稱,不然找不到自定義的tags)

(4)調用自定義的filter和simple_tag。

 

filter能夠用在if等語句後,simple_tag不能夠:

{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

7 extend模板繼承

將shopping_car.html和ordered.html中大量重複的代碼提取出來,寫入base.html中,不一樣的部分分別寫在各自模板中,經過extends繼承base.html中的公共部分。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         *{
 8             margin: 0;
 9         }
10 
11         .top{
12             height: 45px;
13             background-color: darkblue;
14         }
15 
16         .menu{
17             width: 20%;
18             height: 700px;
19             background-color: cornflowerblue;
20             float: left;
21             margin-top: 5px;
22         }
23 
24         .menu a{
25             display: block;
26             text-align: center;
27         }
28 
29         .content{
30             width: 80%;
31             height: 700px;
32             float: left;
33             margin-top: 5px;
34             background-color: lightgray;
35         }
36     </style>
37 </head>
38 <body>
39     <div class="top"></div>
40     <div class="menu">
41         <a href="/shopping_car/">Shopping Car</a>
42         <a href="/ordered/">Ordered</a>
43     </div>
44     <div class="content">
45         {% block content %}
46         {% endblock %}
47     </div>
48 </body>
49 </html>
base.html

shopping_car.html:

1 {% extends 'base.html' %}
2 
3 
4 {% block content %}
5  <a>購物車</a>
6 {% endblock %}

ordered.html:

1 {% extends 'base.html' %}
2 
3 
4 {% block content %}
5  <a>訂單</a>
6 {% endblock %}

 

八 Django modules(模型)

1      django默認支持sqlite,mysql, oracle,postgresql數據庫。

     <1> sqlite

            django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅動

            引擎名稱:django.db.backends.sqlite3

     <2> mysql

            引擎名稱:django.db.backends.mysql

2    mysql驅動程序

          MySQLdb(mysql python)

          mysqlclient

          MySQL

          PyMySQL(純python的mysql驅動程序)

3  Django的項目中默認使用sqlite數據庫,在settings中設置以下:

 若是想要使用mysql數據庫,只須要作以下更改:

注意:NAME即數據庫的名字,在mysql鏈接前該數據庫必須已經建立,而上面的sqlite數據庫下的db.sqlite3則是項目自動建立

         USER和PASSWORD分別是數據庫的用戶名和密碼。

         設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。

         而後,啓動項目,會報錯:no module named MySQLdb

         這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb對於py3有很大問題,因此咱們須要的驅動是PyMySQL

         因此,咱們只須要找到項目名文件下的__init__,在裏面寫入:

ORM(對象關係映射)

對象-關係映射(Object/Relation Mapping,簡稱ORM),是隨着面向對象的軟件開發方法發展而產生的。面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,關係數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關係數據是業務實體的兩種表現形式,業務實體在內存中表現爲對象,在數據庫中表現爲關係數據。內存中的對象之間存在關聯和繼承關係,而在數據庫中,關係數據沒法直接表達多對多關聯和繼承關係。所以,對象-關係映射(ORM)系統通常以中間件的形式存在,主要實現程序對象到關係數據庫數據的映射。  面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關係數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別。爲了解決這個不匹配的現象,對象關係映射技術應運而生。  讓咱們從O/R開始。字母O起源於"對象"(Object),而R則來自於"關係"(Relational)。幾乎全部的程序裏面,都存在對象和關係數據庫。在業務邏輯層和用戶界面層中,咱們是面向對象的。當對象信息發生變化的時候,咱們須要把對象的信息保存在關係數據庫中。  當你開發一個應用程序的時候(不使用O/R Mapping),你可能會寫很多數據訪問層的代碼,用來從數據庫保存,刪除,讀取對象信息,等等。你在DAL中寫了不少的方法來讀取對象數據,改變狀態對象等等任務。而這些代碼寫起來老是重複的。  若是打開你最近的程序,看看DAL代碼,你確定會看到不少近似的通用的模式。咱們以保存對象的方法爲例,你傳入一個對象,爲SqlCommand對象添加SqlParameter,把全部屬性和對象對應,設置SqlCommand的CommandText屬性爲存儲過程,而後運行SqlCommand。對於每一個對象都要重複的寫這些代碼。  除此以外,還有更好的辦法嗎?有,引入一個O/R Mapping。實質上,一個O/R Mapping會爲你生成DAL。與其本身寫DAL代碼,不如用O/R Mapping。你用O/R Mapping保存,刪除,讀取對象,O/R Mapping負責生成SQL,你只須要關心對象就好。  對象關係映射成功運用在不一樣的面向對象持久層產品中,如:Torque,OJB,hibernate,TopLink,Castor JDO, TJDO 等。  

通常的ORM包括如下四部分:  一個對持久類對象進行CRUD操做的API;  一個語言或API用來規定與類和類屬性相關的查詢;  一個規定mapping metadata的工具;  一種技術可讓ORM的實現同事務對象一塊兒進行dirty checking, lazy association fetching以及其餘的優化操做。

1  django ORM——建立表(模型)

    django模型經常使用的字段類型

                字段名

參數

意義

AutoField

 

一個可以根據可用ID自增的 IntegerField

BooleanField

 

一個真/假(true/false)字段

CharField

 (max_length)

一個字符串字段,適用於中小長度的字符串。對於長段的文字,請使用 TextField

CommaSeparatedIntegerField

 (max_length)

一個用逗號分隔開的整數字段

DateField

([auto_now],  [auto_now_add])

日期字段

DateTimeField

 

時間日期字段,接受跟 DateField 同樣的額外選項

EmailField

 

一個能檢查值是不是有效的電子郵件地址的 CharField

FileField

(upload_to)

一個文件上傳字段

FilePathField

(path,[match],[recursive])

一個擁有若干可選項的字段,選項被限定爲文件系統中某個目錄下的文件名

FloatField

(max_digits,decimal_places)

一個浮點數,對應Python中的 float 實例

ImageField

(upload_to,  [height_field] ,[width_field])

像 FileField 同樣,只不過要驗證上傳的對象是一個有效的圖片。

IntegerField

 

一個整數。

IPAddressField

 

一個IP地址,以字符串格式表示(例如: "24.124.1.30" )。

NullBooleanField

 

就像一個  BooleanField ,但它支持 None /Null 。

PhoneNumberField 

 

它是一個  CharField ,而且會檢查值是不是一個合法的美式電話格式

PositiveIntegerField 

 

和  IntegerField 相似,但必須是正值。

PositiveSmallIntegerField 

 

與  PositiveIntegerField 相似,但只容許小於必定值的值,最大值取決於數據庫.

SlugField

 

 嵌條 就是一段內容的簡短標籤,這段內容只能包含字母、數字、下

劃線或連字符。一般用於URL中

SmallIntegerField

 

和  IntegerField 相似,可是隻容許在一個數據庫相關的範圍內的數值(一般是-32,768到

+32,767)

TextField

 

一個不限長度的文字字段

TimeField

 

時分秒的時間顯示。它接受的可指定參數與 DateField 和 DateTimeField 相同。

URLField

 

用來存儲URL的字段。

USStateField

 

美國州名稱縮寫,兩個字母。

XMLField

(schema_path)

它就是一個  TextField ,只不過要檢查值是匹配指定schema的合法XML。

 

 參數名

意義

null

若是設置爲 True 的話,Django將在數據庫中存儲空值爲 NULL 。默認爲 False 。

blank

若是是 True ,該字段容許留空,默認爲 False 。

choices

一個包含雙元素元組的可迭代的對象,用於給字段提供選項。

db_column

當前字段在數據庫中對應的列的名字。

db_index

若是爲 True ,Django會在建立表格(好比運行 manage.py syncdb )時對這一列建立數據庫索引。

default

字段的默認值

editable

若是爲 False ,這個字段在管理界面或表單裏將不能編輯。默認爲 True 。

help_text

在管理界面表單對象裏顯示在字段下面的額外幫助文本。

primary_key

若是爲 True ,這個字段就會成爲模型的主鍵。

radio_admin

默認地,對於  ForeignKey 或者擁有 choices  設置的字段,Django管理界面會使用列表選擇框(<select>)。若是 radio_admin 設置爲 True 的話,Django就會使用單選按鈕界面。

unique

若是是 True ,這個字段的值在整個表中必須是惟一的。

unique_for_date

把它的值設成一個  DataField 或者  DateTimeField 的字段的名稱,能夠確保字段在這個日期內不會出現重複值。

unique_for_month

  unique_for_date 相似,只是要求字段在指定字段的月分內惟一。

unique_for_year

  unique_for_date 及 unique_for_month 相似,只是時間範圍變成了一年。

verbose_name

ForeignKey  、  ManyToManyField 和 OneToOneField 以外的字段都接受一個詳細名稱做爲第一個位置參數。

 

實例:建立一個書籍、做者、出版社數據庫結構

一本書可能有多個做者,一個做者能夠寫多本書,一本書一般僅由一個出版社出版。所以做者與書爲多對多關係,出版社與書爲一對多關係。接下來,咱們來建立表(模型)。

多對多關係(many-to-many):彼此一對多,自動建立第三張表來表示對應關係。

一對多關係(one-to-many):主外鍵關係,在many對應的表中給須要的字段添加外鍵。

一對一(one-to-one):在一對多基礎上,在多的哪一個表ForeignKey的基礎上加unique=true。

1  每一個數據模型都是django.db.models.Model的子類,它的父類Model包含了全部必要的和數據庫交互的方法。並提供了一個簡介漂亮的定義數據庫字段的語法。      

2  每一個模型至關於單個數據庫表(多對多關係例外,會多生成一張關係表),每一個屬性也是這個表中的字段。屬性名就是字段名,它的類型(例如CharField)至關於數據庫的字段類型(例如varchar)。

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class Publisher(models.Model):
 5 
 6     name = models.CharField(max_length=64,verbose_name="出版社名稱")
 7     city = models.CharField(max_length=24,verbose_name="所在城市")
 8 
 9 
10     def __str__(self):
11 
12         return self.name
13 
14 
15 class Author(models.Model):
16 
17     name = models.CharField(max_length=20,verbose_name="做者名稱")
18     sex = models.BooleanField(max_length=1,choices=((0,''),(1,'')))
19     email = models.EmailField()
20     birthday = models.DateField()
21 
22     def __str__(self):
23 
24         return self.name
25 
26 
27 class Book(models.Model):
28 
29     title = models.CharField(max_length=64,verbose_name="書名")
30     authors = models.ManyToManyField(Author)
31     publish = models.ForeignKey(Publisher)
32     price = models.DecimalField(max_digits=5,decimal_places=2,default=10)
33 
34     def __str__(self):
35 
36         return self.title
建立模型

確認當前app已經添加到settings設置中,而後執行數據庫初始化操做: python3 manage.py makemigrationspython3 manage.py migrate

2  django ORM——增(create、save)

增長數據有兩種方式: (數據表中的每一條數據表明一個對象)

建立一對多關係:

建立多對多關係:

3  django ORM——刪(delete)

 

4  django ORM——改(update、save)

 只有QuerySet對象纔有update方法,所以查找行對象時只能使用filter,不能使用get。返回的整數表示受影響的行數。

save方法會將全部屬性從新設定一遍,而update只對指定的屬性值進行設定,故update方法更高效。

5  django ORM——查

 1 # 查詢相關API:
 2 
 3 #  <1>filter(**kwargs):      它包含了與所給篩選條件相匹配的對象
 4 
 5 #  <2>all():                 查詢全部結果
 6 
 7 #  <3>get(**kwargs):         返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
 8 
 9 #-----------下面的方法都是對查詢的結果再進行處理:好比 objects.filter.values()--------
10 
11 #  <4>values(*field):        返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列
12                                      
13 #  <5>exclude(**kwargs):     它包含了與所給篩選條件不匹配的對象
14 
15 #  <6>order_by(*field):      對查詢結果排序
16 
17 #  <7>reverse():             對查詢結果反向排序
18 
19 #  <8>distinct():            從返回結果中剔除重複紀錄
20 
21 #  <9>values_list(*field):   它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
22 
23 #  <10>count():              返回數據庫中匹配查詢(QuerySet)的對象數量。
24 
25 # <11>first():               返回第一條記錄
26 
27 # <12>last():                返回最後一條記錄
28 
29 #  <13>exists():             若是QuerySet包含數據,就返回True,不然返回False。
查詢API:
>>> Book.objects.all()
<QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]>
>>> Book.objects.filter(price__lt=50)
<QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]>
>>> Book.objects.get(title='python')
<Book: python>
>>> Book.objects.filter(price__lt=50).values()
<QuerySet [{'title': 'python紅寶書', 'price': Decimal('8.00'), 'publish_id': 4, 'id': 3}, {'title': '杜拉拉大結局', 'price': Decimal('32.00'), 'publish_id': 3, 'id': 6}, {'title': '百年孤獨', 'price': Decimal('39.50'), 'publish_id': 4, 'id': 7}]>
>>> Book.objects.filter(price__lt=50).exclude(price__gt=60)
<QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]>
>>> Book.objects.filter(price__lt=50).exclude(id=6)
<QuerySet [<Book: python紅寶書>, <Book: 百年孤獨>]>
>>> Book.objects.all().order_by('price')
<QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>, <Book: C語言>, <Book: php>, <Book: python>, <Book: C++>]>
>>> Book.objects.all().reverse()
<QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]>
>>> Book.objects.all().distinct()
<QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]>
>>> Book.objects.all().values_list()
<QuerySet [(1, 'python', 1, Decimal('78.00')), (2, 'php', 2, Decimal('54.00')), (3, 'python紅寶書', 4, Decimal('8.00')), (4, 'C語言', 2, Decimal('50.00')), (5, 'C++', 1, Decimal('78.00')), (6, '杜拉拉大結局', 3, Decimal('32.00')), (7, '百年孤獨', 4, Decimal('39.50'))]>
>>> Book.objects.all().count()
7
>>> Book.objects.all().first()
<Book: python>
>>> Book.objects.all().last()
<Book: 百年孤獨>
>>> Book.objects.all().exists()
True
View Code

   擴展查詢:

#擴展查詢,有時候DJANGO的查詢API不能方便的設置查詢條件,提供了另外的擴展查詢方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  

extra
View Code

   惰性機制:

Book.objects.filter()或Book.objects.all()等只是返回一個QuerySet對象(查詢結果集對象),並不會立刻執行SQL,而是當調用QuerySet對象時纔會執行SQL。

   QuerySet特色:

    <1>可迭代

   

    <2>可切片

  

  QuerySet的高效使用:

 1 #<1>Django的queryset是惰性的
 2 
 3 Django的queryset對應於數據庫的若干記錄(row),經過可選的查詢來過濾。例如,下面的代碼會獲得數據庫中
 4 名字爲‘Dave’的全部的人:
 5 person_set = Person.objects.filter(first_name="Dave")
 6 
 7 上面的代碼並無運行任何的數據庫查詢。你可使用person_set,給它加上一些過濾條件,或者將它傳給某個函數,
 8 這些操做都不會發送給數據庫。這是對的,由於數據庫查詢是顯著影響web應用性能的因素之一。
 9 
10 #<2>要真正從數據庫得到數據,你能夠遍歷queryset或者使用if queryset,總之你用到數據時就會執行sql.
11    爲了驗證這些,須要在settings里加入 LOGGING(驗證方式)
12 
13         obj=models.Book.objects.filter(id=3)
14 
15         # for i in obj:
16         #     print(i)
17 
18         # if obj:
19         #     print("ok")
20 
21 #<3>queryset是具備cache的
22 當你遍歷queryset時,全部匹配的記錄會從數據庫獲取,而後轉換成Django的model。這被稱爲執行(evaluation).
23 這些model會保存在queryset內置的cache中,這樣若是你再次遍歷這個queryset,你不須要重複運行通用的查詢。
24         obj=models.Book.objects.filter(id=3)
25 
26         # for i in obj:
27         #     print(i)
28 
29         # for i in obj:
30         #     print(i)   #LOGGING只會打印一次
31 
32 
33 #<4>
34      簡單的使用if語句進行判斷也會徹底執行整個queryset而且把數據放入cache,雖然你並不須要這些數據!
35 爲了不這個,能夠用exists()方法來檢查是否有數據:
36 
37 obj = Book.objects.filter(id=4)
38 #  exists()的檢查能夠避免數據放入queryset的cache。
39 if obj.exists():
40     print("hello world!")
41 
42 #<5>當queryset很是巨大時,cache會成爲問題
43 
44 處理成千上萬的記錄時,將它們一次裝入內存是很浪費的。更糟糕的是,巨大的queryset可能會鎖住系統進程,讓你的
45 程序瀕臨崩潰。要避免在遍歷數據的同時產生queryset cache,可使用iterator()方法來獲取數據,處理完數據就
46 將其丟棄。
47 objs = Book.objects.all()
48 # iterator()能夠一次只從數據庫獲取少許數據,這樣能夠節省內存
49 for obj in objs.iterator():
50     print(obj.name)
51 固然,使用iterator()方法來防止生成cache,意味着遍歷同一個queryset時會重複執行查詢。因此使用iterator()
52 的時候要小心,確保你的代碼在操做一個大的queryset時沒有重複執行查詢
53 
54 總結:
55     queryset的cache是用於減小程序對數據庫的查詢,在一般的使用下會保證只有在須要的時候纔會查詢數據庫。
56 使用exists()和iterator()方法能夠優化程序對內存的使用。不過,因爲它們並不會生成queryset cache,可能
57 會形成額外的數據庫查詢。
View Code

 對象查詢、單表條件查詢、多表條件關聯查詢:

 1 #--------------------對象形式的查找--------------------------
 2     # 正向查找
 3     ret1=models.Book.objects.first()
 4     print(ret1.title)
 5     print(ret1.price)
 6     print(ret1.publisher)
 7     print(ret1.publisher.name)  #由於一對多的關係因此ret1.publisher是一個對象,而不是一個queryset集合
 8 
 9     # 反向查找
10     ret2=models.Publish.objects.last()
11     print(ret2.name)
12     print(ret2.city)
13     #如何拿到與它綁定的Book對象呢?
14     print(ret2.book_set.all()) #ret2.book_set是一個queryset集合
15 
16 #---------------了不得的雙下劃線(__)之單表條件查詢----------------
17 
18 #    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值
19 #
20 #    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據
21 #    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
22 #
23 #    models.Tb1.objects.filter(name__contains="ven")
24 #    models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
25 #
26 #    models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and
27 #
28 #    startswith,istartswith, endswith, iendswith,
29 
30 #----------------了不得的雙下劃線(__)之多表條件關聯查詢---------------
31 
32 # 正向查找(條件)
33 
34 #     ret3=models.Book.objects.filter(title='Python').values('id')
35 #     print(ret3)#[{'id': 1}]
36 
37       #正向查找(條件)之一對多
38 
39       ret4=models.Book.objects.filter(title='Python').values('publisher__city')
40       print(ret4)  #[{'publisher__city': '北京'}]
41       ret5=models.Book.objects.filter(publisher__address='北京').values('publisher__name')
42       print(ret5)   #[{'publisher__name': '人大出版社'}, {'publisher__name': '人大出版社'}]
43 
44       #正向查找(條件)之多對多
45       ret6=models.Book.objects.filter(title='Python').values('author__name')
46       print(ret6)
47       ret7=models.Book.objects.filter(author__name="alex").values('title')
48       print(ret7)
49 
50 # 反向查找(條件)
51 
52     #反向查找之一對多:
53     ret8=models.Publisher.objects.filter(book__title='Python').values('name')
54     print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的關聯表名
55 
56     ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
57     print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]
58 
59     #反向查找之多對多:
60     ret10=models.Author.objects.filter(book__title='Python').values('name')
61     print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]
View Code
>>> Publisher.objects.filter(book__price__gt=50).values('book__title')
<QuerySet [{'book__title': 'python'}, {'book__title': 'php'}, {'book__title': 'C++'}]>

聚合查詢和分組查詢:

 <1> aggregate(*args,**kwargs)

from django.db.models import Avg,Min,Sum,Max

從整個查詢集生成統計值。好比,你想要計算全部在售書的平均價錢。Django的查詢語法提供了一種方式描述全部
圖書的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的參數描述了咱們想要計算的聚合值,在這個例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的
標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。若是你想要爲聚合值指定
一個名稱,能夠向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


若是你也想知道全部圖書價格的最大值和最小值,能夠這樣查詢:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
View Code

<2> annotate(*args,**kwargs)

能夠經過計算查詢結果中每個對象所關聯的對象集合,從而得出總計值(也能夠是平均值或總和),即爲查詢集的每一項生成聚合。

       查詢alex出的書總價格                   

       

 

        查詢各個做者出的書的總價格,這裏就涉及到分組了,分組條件是authors__name

 

            

 

         查詢各個出版社最便宜的書價是多少

 

       

 

F查詢和Q查詢:

 1 # F 使用查詢條件的值,專門取對象中某列值的操做
 2 
 3     # from django.db.models import F
 4     # models.Tb1.objects.update(num=F('num')+1)
 5 
 6 
 7 # Q 構建搜索條件
 8     from django.db.models import Q
 9 
10     #1 Q對象(django.db.models.Q)能夠對關鍵字參數進行封裝,從而更好地應用多個查詢
11     q1=models.Book.objects.filter(Q(title__startswith='P')).all()
12     print(q1)#[<Book: Python>, <Book: Perl>]
13 
14     # 二、能夠組合使用&,|操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象。
15     Q(title__startswith='P') | Q(title__startswith='J')
16 
17     # 三、Q對象能夠用~操做符放在前面表示否認,也可容許否認與不否認形式的組合
18     Q(title__startswith='P') | ~Q(pub_date__year=2005)
19 
20     # 四、應用範圍:
21 
22     # Each lookup function that takes keyword-arguments (e.g. filter(),
23     #  exclude(), get()) can also be passed one or more Q objects as
24     # positional (not-named) arguments. If you provide multiple Q object
25     # arguments to a lookup function, the arguments will be 「AND」ed
26     # together. For example:
27 
28     Book.objects.get(
29         Q(title__startswith='P'),
30         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
31     )
32 
33     #sql:
34     # SELECT * from polls WHERE question LIKE 'P%'
35     #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
36 
37     # import datetime
38     # e=datetime.date(2005,5,6)  #2005-05-06
39 
40     # 五、Q對象能夠與關鍵字參數查詢一塊兒使用,不過必定要把Q對象放在關鍵字參數查詢的前面。
41     # 正確:
42     Book.objects.get(
43         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
44         title__startswith='P')
45     # 錯誤:
46     Book.objects.get(
47         question__startswith='P',
48         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
View Code

 

原生SQL的用法:

http://www.cnblogs.com/lijintian/p/6100097.html 

附錄 Django命令行工具

django-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每個Django Project裏都會有一個mannage.py。

1 django-admin.py startproject project_name

建立一個新的django工程。

2 python manage.py startapp app_name

建立一個應用。

3 python manage.py runserver 8080

啓動django項目。

4 python manage.py makemigrations

migrations目錄下生成同步數據庫的腳本。

同步數據庫python manage.py migrate

5 python manage.py createsuperuser

建立超級管理員,設置用戶名和密碼。當咱們訪問http://http://127.0.0.1:8080/admin/時,即可以經過超級管理員用戶登陸了。

6 python manage.py flush

清空數據庫。

7 django-admin.py help startapp

查詢某個命令的詳細信息。

8 python manage.py shell

啓動交互界面。

9 python manage.py

查看django提供的命令。

相關文章
相關標籤/搜索