Django之Model(一)--基礎篇

 0、數據庫配置

django默認支持sqlite,mysql, oracle,postgresql數據庫。Django鏈接數據庫默認編碼使用UTF8,使用中文不須要特別設置。html

sqlite
    django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅
    引擎名稱:django.db.backends.sqlite3
mysql
    引擎名稱:django.db.backends.mysql

mysql引擎配置:python

'defaults': {
  'ENGINE': 'django.db.backends.mysql',
  'NAME':'127.0.0.1',
  'USER':'root',
  'PASSWORD':'',
  } mysql

 

mysql引擎底層驅動的py3支持問題:git

mysql驅動程序
    MySQLdb(mysql python),Django默認使用改驅動,但改驅動在python3下存在兼容性問題。所以使用PyMySQL。
    PyMySQL(純python的mysql驅動程序)
mysql驅動python3解決方法
    找到項目名文件下的__init__,在裏面寫入:
    import pymysql
    pymysql.install_as_MySQLdb()    

 

 

1、Model類定義

一、Model類建立

下面這個模型類將做爲本篇博客的基礎模型,全部的實例都基於此。web

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名稱")
    website = models.URLField()
    # book_set     反向關聯一對多字段的Book
    def __unicode__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=30)
    # authordetail  反向關聯一對一字段AuthorDetail表
    # book_set      反向關聯一對多字段的Book
    def __unicode__(self):
        return self.name
class AuthorDetail(models.Model):
    sex = models.BooleanField(max_length=1, choices=((0, ''),(1, ''),))
    author = models.OneToOneField(Author)
    # author_id隱藏字段,正向關聯一對一字段的Author對象的id

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher,null=True)
    # publisher_id隱藏字段,正向關聯一對多字段的Publisher對象的id
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
    def __unicode__(self):
        return self.title
#coding:utf-8
from __future__ import unicode_literals

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名稱")
    website = models.URLField()
    def __unicode__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=30)
    def __unicode__(self):
        return self.name

class AuthorDetail(models.Model):
    sex = models.BooleanField(max_length=1, choices=((0, ''),(1, ''),))
    author = models.OneToOneField(Author)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author,through='Book2Author')
    publisher = models.ForeignKey(Publisher)
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
    def __unicode__(self):
        return self.title

class Book2Author(models.Model):
    book = models.ForeignKey(Book)
    author = models.ForeignKey(Author)
    groupname = models.CharField(max_length=100)

#默認多對多關係Django自動爲咱們建立了一張中間表,僅提供3個字段,兩個關聯表的外鍵字段和一個id字段。
#這種使用自定義中間表的方式,使得咱們能夠自定義的爲中間表添加額外的字段。當咱們須要爲多對多關係提供額外字段時,用此方式。
自定義多對多中間表

二、同步數據庫

模型表建立和更新的時候是要使用數據庫遷移命令,使模型類的改變同步到數據庫。正則表達式

makemigrations    #建立變動記錄
migrate    #同步到數據庫

三、Model類(表)關係圖:

名詞說明:sql

  正向查詢,從定義關係字段的類中去查詢關係對象的值或值的集合。舉個栗子:從AuthorDetail類中查詢關聯字段author對象的值。數據庫

  反向查詢,從本類中查詢被關聯對象中的值或值的集合。舉個栗子:從Author對象中查詢被關聯字段AuthorDetail對象的值。express

四、字段類型:

一、models.AutoField  自增列 = int(11)
  若是沒有的話,默認會生成一個名稱爲 id 的列,若是要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。
2、models.CharField  字符串字段
  必須 max_length 參數
三、models.BooleanField  布爾類型=tinyint(1)
  不能爲空,Blank=True
四、models.ComaSeparatedIntegerField  用逗號分割的數字=varchar
  繼承CharField,因此必須 max_lenght 參數
5、models.DateField  日期類型 date
  對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。
6、models.DateTimeField  日期類型 datetime
  同DateField的參數
七、models.Decimal  十進制小數類型 = decimal
  必須指定整數位max_digits和小數位decimal_places
八、models.EmailField  字符串類型(正則表達式郵箱) =varchar
  對字符串進行正則表達式
九、models.FloatField  浮點類型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  長整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串類型(ip4正則表達式)
13、models.GenericIPAddressField  字符串類型(ip4和ip6是可選的)
  參數protocol能夠是:both、ipv四、ipv6
  驗證時,會根據設置報錯
14、models.NullBooleanField  容許爲空的布爾類型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  減號、下劃線、字母、數字
18、models.SmallIntegerField  數字
  數據庫中的字段有:tinyint、smallint、int、bigint
1九、models.TextField  字符串=longtext
20、models.TimeField  時間 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正則表達式
22、models.BinaryField  二進制
23、models.ImageField   圖片
2四、models.FilePathField 文件
ORM字段類型

五、字段選項:

一、null=True
  數據庫中字段是否能夠爲空
二、blank=True
  django的 Admin 中添加數據時是否可容許空值
三、primary_key = False
  主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自動建立---不管添加或修改,都是當前操做的時間
  auto_now_add  自動建立---永遠是建立時的時間
5、choices    配置可選項
GENDER_CHOICE = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length    最大長度
7、default  默認值
8、verbose_name  Admin中字段的顯示名稱
九、name|db_column  數據庫中的字段名稱
十、unique=True  不容許重複
十一、db_index = True  數據庫索引
十二、editable=True  在Admin裏是否可編輯
1三、error_messages=None  錯誤提示
1四、auto_created=False  自動建立
15、help_text  在Admin中提示幫助信息
1六、validators=[]    自定義數據格式驗證
1七、upload-to    上傳文件路徑
字段選項 

六、Model類的Meta(元數據)選項:

abstract=False     True就表示模型是抽象基類
db_table = 'music_album'    自定義數庫的表名稱前綴
get_latest_by = "datefield_name"    根據時間字段datefield_name排序,latest()和earliest()方法中使用的默認字段。
db_tablespace        當前模型所使用的數據庫表空間的名字。默認值是項目設置中的DEFAULT_TABLESPACE。若是後端並不支持表空間,這個選項能夠忽略。
ordering = ['-fieldname']    對象默認的順序,字段前面帶有'-'符號表示逆序,不然正序。排序會增長查詢額外開銷。
proxy = True    它做爲另外一個模型的子類,將會做爲一個代理模型。
unique_together    設置聯合惟一。ManyToManyField不能包含在unique_together中。
index_together    設置聯合索引。
        index_together = [
            ["pub_date", "deadline"],
        ]
        方便起見,處理單一字段的集合時index_together = ["pub_date", "deadline"]

verbose_name    在Admin裏,個易於理解的表名稱,爲單數:verbose_name = "pizza"
verbose_name_plural        在Admin裏顯示的表名稱,爲複數:verbose_name_plural = "stories",通常同verbose_name一同設置。
Meta元數據選項

2、對象CURD操做

2.1 基礎對象CURD(無關聯字段)

一、增django

方法一:
author= Author(name="魯迅")
author.save()

方法二:
建立對象並同時保存對象的快捷方法,存在關係字段時沒法用此方法建立。
create(**kwargs)
Author.objects.create(name=u"魯迅")

方法三:
批量建立
bulk_create(objs, batch_size=None) ret=Blog.objects.bulk_create([ Author(name="徐志摩"), Author(name="李白")]) 

方法四:
存在就獲取,不存在就建立
get_or_create(defaults=None,**kwargs),
defaults必須爲一個字典,在建立時生效的默認值;**kwargs爲查詢條件。
建立對象時,使用**kwargs和defaults共同做用,取交集,defaults優先。

updated_values={"name":u"美猴王"}
a、存在就獲取,查詢到結果多餘一個出錯MultipleObjectsReturned
ret=Author.objects.get_or_create(name=u'徐志摩',defaults=updated_values)
ret:(<Author: 徐志摩>, False)
b、不存在就建立
ret=Author.objects.get_or_create(name=u'徐志摩',defaults=updated_values)
ret:(<Author: 美猴王>, True)

方法五:
存在就更新,不存在就建立
update_or_create(defaults=None, **kwargs)
a、存在就更新
updated_values={"name":u"猴王"}
ret=Author.objects.update_or_create(defaults=updated_values,name=u"猴子")
ret:(<Author: 猴王>, False)
根據給出的查詢條件name=u"猴子"查找對象,查詢到結果就使用defaults字典去更新對象。

b、不存在就建立
ret=Author.objects.update_or_create(defaults=updated_values,name=u"猴子1")
ret:(<Author: 猴王>, True)
defaults必須爲一個字典,在建立時生效的默認值;**kwargs爲查詢條件。
建立對象時,使用**kwargs和defaults共同做用,取交集,defaults優先。
二、刪
使用delete會查找出相關表中的有關聯的數據行一併刪除
方法一:
Author.objects.filter(name="徐志摩").delete()
(1, {u'otest.Book_authors': 0, u'otest.AuthorDetail': 0, u'otest.Author': 1})
方法二:
a9=Author.objects.get(name="魯迅")
a9.delete()
三、改
方法一:
update(**kwargs)返回更新的行數,批量修改
ret=Author.objects.filter(name='秋雨').update(name="陶淵明")

方法二:
單條修改
a7=Author.objects.get(name="清風")
a7.name=u"宋清風"
a7.save()
四、查
a、查詢結果非QuertSet
get(**kwargs)
    在使用 get() 時,若是符合篩選條件的對象超過一個,就會拋出 MultipleObjectsReturned 異常。
    在使用 get() 時,若是沒有找到符合篩選條件的對象,就會拋出 DoesNotExist 異常。
    from django.core.exceptions import ObjectDoesNotExist
    try:
        e = Entry.objects.get(id=3)
        b = Blog.objects.get(id=1)
    except ObjectDoesNotExist:
        print("Either the entry or blog doesn't exist.")
    
in_bulk(id_list)
    接收一個主鍵值列表,而後根據每一個主鍵值所其對應的對象,返回一個主鍵值與對象的映射字典。
    Author.objects.in_bulk([1,2,3])
    {1: <Author: 蒼松>, 2: <Author: 猴王>, 3: <Author: 宋清風>}
    
first()    查詢第一條,通常使用前先排序,或者肯定其只有一條數據。
last()    查詢最後一條,同上

count()        返回數據庫中匹配查詢(QuerySet)的對象數量。 count() 不會拋出任何異常。

exists()    若是 QuerySet 包含有數據,就返回 True 不然就返回 False。這多是最快最簡單的查詢方法了。

latest(field_name=None)    ,根據時間字段 field_name 獲得最新的對象。
earliest(field_name=None),    根據時間字段 field_name 獲得最老的對象。
#F使用查詢條件的值,進行數值計算

from django.db.models import F
Book.objects.filter(id=1).update(price=F('price')+10)

b、查詢結果爲QuerySet

 經常使用方法:

一、filter(**kwargs)
    過濾,返回一個新的QuerySet,包含與給定的查詢參數匹配的對象。
    >>>q=Author.objects.filter(name=u"蒼松")
    >>> q
    [<Author: 蒼松>]

二、exclude(**kwargs)
    反過濾,返回一個新的QuerySet,它包含不知足給定的查找參數的對象。功能與filter相反。

三、values(*fields)
    返回一個新的QuerySet,但迭代時返回字典而不是模型實例對象。    
    *fields表示須要取哪些字段,空表示取全部字段。
    >>> q=Author.objects.values("id")
    >>> q
    [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}, {'id': 18}, {'id': 22}, {'id': 24}]


四、values_list(*fields, flat=False)
    返回一個新的QuerySet,但迭代時返回元組而不是模型實例對象。
    *fields表示須要取哪些字段,空表示取全部字段。flat=True表示返回的結果爲單個值而不是元組,多個字段時不能使用flat。
    >>> q=Author.objects.values_list("id")
    >>> q
    [(1,), (2,), (3,), (4,), (18,), (22,), (24,)]
    >>> q=Author.objects.values_list("id",flat=True)
    >>> q
    [1, 2, 3, 4, 18, 22, 24]    


5、all()
    返回當前 QuerySet全部對象。

六、select_related(*field)
    返回一個QuerySet,使用JOIN語句連表查詢。它會在執行查詢時自動跟蹤外鍵關係,一次讀取全部外鍵關聯的字段,並儘量地深刻遍歷外鍵鏈接,以減小數據庫的查詢。但數據關係鏈複雜的查詢須要慎用。僅對外鍵生效。

七、prefetch_related(*field)
    prefetch_related()的解決方法是,分別查詢每一個表,而後用Python處理他們之間的關係。外鍵和多對多都生效。    

    
八、order_by(*fields)
    排序,返回一個新的QuerySet,隱式的是升序排序,-name表示根據name降序
    >>> q=Author.objects.order_by("name")
    >>> q
    [<Author: au>, <Author: 宋清風>, <Author: 猴王>, <Author: 美猴王>, <Author: 蒼松>, <Author: 趙清風>, <Author: 陶淵明>]
    >>> q=Author.objects.order_by("-name")
    >>> q
    [<Author: 陶淵明>, <Author: 趙清風>, <Author: 蒼松>, <Author: 美猴王>, <Author: 猴王>, <Author: 宋清風>, <Author: au>]

9、reverse()
    reverse()方法返回反向排序的QuerySet。
    必須對一個已經排序過的queryset(也就是q.ordered=True)執行reverse()纔有效果。

十、distinct([*fields])
    去重複。返回一個在SQL 查詢中使用SELECT DISTINCT 的新QuerySet。    
一、dates(field, kind, order='ASC')
    field 是你的 model 中的 DateField 字段名稱。
    kind 是 「year」, 「month」 或 「day」 之一。 每一個 datetime.date對象都會根據所給的 type 進行截減。
        「year」 返回全部時間值中非重複的年分列表。
        「month」 返回全部時間值中非重複的年/月列表。
        「day」 返回全部時間值中非重複的年/月/日列表。
    order, 默認是 ‘ASC’,只有兩個取值 ‘ASC’ 或 ‘DESC’。它決定結果如何排序。

二、datetimes(field, kind, order=’ASC’)
    返回一個 DateTimeQuerySet,參數與dates相似,多了"hour", "minute" ,"second"    
    
3、none()
    返回一個 EmptyQuerySet,它是一個運行時只返回空列表的 QuerySet。它常常用在這種場合:你要返回一個空列表,可是調用者卻須要接收一個 QuerySet 對象。

四、defer(*fields)
    將不想載入的字段的名稱傳給 defer() 方法,就能夠作到延後載入。
    在某些數據複雜的環境下,你的 model 可能包含很是多的字段,可能某些字段包含很是多的數據(好比,文檔字段),或者將其轉化爲Python對象會消耗很是多的資源。在這種狀況下,有時你可能並不須要這種字段的信息,那麼你可讓 Django 不讀取它們的數據。

五、only(*fields)
    only() 方法或多或少與 defer() 的做用相反。若是你在提取數據時但願某個字段不該該被延後載入,而應該當即載入,那麼你就能夠作使用 only()方法。
    
6、多數據庫切換using(alias)
    單獨使用無心義,配合其餘查詢集方法一塊兒使用。
    Author.objects.using('backup')

七、表鎖定select_for_update(nowait=False)
    單獨使用無心義,配合其餘查詢集方法一塊兒使用。    
    返回queryset,並將須要更新的行鎖定,相似於SELECT … FOR UPDATE的操做。
    entries = Entry.objects.select_for_update().filter(author=request.user)
    全部匹配的entries都會被鎖定直到這次事務結束。
其餘方法
特別的:QuerySet可使用切片限制查詢集。
切片後依舊得到QuerySet,而且不會觸發數據庫查詢。    
>>> a=Author.objects.all()[0:2]
>>> type(a)
<class 'django.db.models.query.QuerySet'>

設置步長值後,得到到List類型值。觸發數據庫查詢
>>> a=Author.objects.all()[::2]
>>> type(a)
<type 'list'>

使用索引,數據對象,觸發數據庫查詢
>>> Author.objects.all()[0]  #等價於Author.objects.all()[0:1].get()
<Author: 蒼松>
查看QuerySet的原始SQL語句
關於查看QuerySet的原始SQL語句,使用查詢集的query對象。
    >>> q=Author.objects.all()
    >>> print q.query
    SELECT "otest_author"."id", "otest_author"."name" FROM "otest_author"

 

 c、查詢條件(雙下劃線)

 全部使用查詢條件的查詢和查詢集過濾的方法(get,get_or_create,filter,exclude等)均可以使用雙下劃線組合出更復雜的查詢條件。

另外一種使用雙下劃線的狀況就是跨表條件查詢單狀況,見下一節關聯字段中跨表查詢。

查詢條件格式
    field__條件類型,例如a=Author.objects.get(id__exact=1)
    默認爲精確匹配
    例如:Author.objects.get(id=1)等價於Author.objects.get(id__exact=1)


1、精確匹配
    exact    精確匹配: Blog.objects.get(id__exact=1)
    iexact    忽略大小寫的精確匹配,Blog.objects.filter(name__iexact='blog7')
2、模糊匹配
(模糊匹配,僅PostgreSQL 和 MySQL支持. SQLite的LIKE 語句不支持大小寫敏感特性,所以模糊匹配對於 SQLite沒法對大敏感)
    contains    大小寫敏感的內容包含測試:Blog.objects.filter(name__contains='blog7')
    icontains    大小寫不敏感的內容包含測試:
    startswith    大小寫敏感的內容開頭 Blog.objects.filter(name__startswith="blog")
    endswith    大小寫敏感的內容結尾 endswith. 
    istartswith    大小寫不敏感的內容開頭 startswith.
    iendswith    大小寫不敏感的內容結尾 endswith.

3、正則匹配
regex
    大小寫敏感的正則表達式匹配。
    它要求數據庫支持正則表達式語法,而 SQLite 卻沒有內建正則表達式支持,所以 SQLite 的這個特性是由一個名爲 REGEXP 的 Python 方法實現的,因此要用到 Python 的正則庫 re.
    Entry.objects.get(title__regex=r'^(An?|The) +')
    等價於 SQL:
    SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
    SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'c'); -- Oracle
    SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
    SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

iregex
    忽略大小寫的正則表達式匹配。


4、範圍匹配
    gt    大於: Blog.objects.filter(id__gt=3)
    gte    大於等於.
    lt    小於.
    lte    小於等於.
    ne    不等於.
    in    位於給定列表中: Blog.objects.filter(id__in=[1,3,5])
    range    範圍測試: Blog.objects.filter(name__range=('blog1','blog5'))

日期匹配:
    year    對 date/datetime 字段, 進行精確的 年 匹配:Polls.objects.filter(pub_date__year=2005).
    month
    day    
    hour
    minute
    second

空值匹配
    isnull    True/False; 作 IF NULL/IF NOT NULL 查詢:Blog.objects.filter(name__isnull=True)

d、 複雜查詢條件,使用Q 對象進行復雜的查詢

filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是須要執行更復雜的查詢(例如OR 語句),你可使用Q 對象。

Q對象有兩種使用方式,一種使用Tree模式。另外一種是使用"|""&"符號進行與或操做。

Q構建搜索條件
    from django.db.models import Q
    con = Q()
    
    q1 = Q()
    q1.connector = 'OR'
    q1.children.append(('id', 1))
    q1.children.append(('id', 2))        
    #等價於Q(id=1) | Q(id=2)

    q2 = Q()
    q2.connector = 'AND'
    q2.children.append(('id', 1))
    q2.children.append(('name__startswith', 'a'))    
    #等價於Q(id=1) | Q(name__startswith='a')

    con.add(q1, 'AND')
    con.add(q2, 'AND')
    
Q搜索能夠和普通查詢參數一塊兒使用,但查詢參數須要在最後。
Author.objects.filter(q1,id=26)

 2.2關聯字段CURD操做(一對一,一對多,多對多表關係操做)

一對一和多對多的表關係的增刪改查
    a1 = Author.objects.get(name="猴子")
    a2 = Author.objects.get(name="蒼松")
    a3 = Author.objects.get(name="魯迅")
    p1=Publisher.objects.get(name="機械出版社")
    p2=Publisher.objects.get(name="av")

==============正向關係操做===================================================
    b1=Book(title="紅樓夢",price=10)
    b1.publisher=p1或者b1.publisher_id=1    #一對多
    b1.save()    先保存book對象以後才能添加多對多關係
    b1.authors.add(a1,a2)或者b1.authors=[a1,a2]    #多對多
    b1.save()


    b1.publisher=None或者b1.publisher_id=None    #一對多    
    b1.authors.remove(a1,a2)    其實是刪除關係表otest_book_authors中的一條數據    #多對多
    b1.authors.clear()            清空全部關係    #多對多
 查詢
  Book.objects.filter(publisher__name=u"
機械出版社")  #一對多,使用雙下劃線
  Book.objects.filter(authors__name=u"蒼松")  
#多對多,使用雙下劃線
獲取字段值對象
    b2.publisher    #一對多,對象下面的字段值繼續使用.獲取。例如b2.publisher.name
    b1.authors.all()    #多對多

==============反向關係操做===================================================
    p1.book_set.add(b1)        #一對多,會更新現有的關係。(一個對象只能有一個外鍵)
    a3.book_set.add(b1)        #多對多

    p1.book_set.remove(b1)    #一對多
    a3.book_set.remove(b1)    #多對多    
    a3.book_set.clear()        #多對多,清空全部關係
 獲取字段值對象
    a2.book_set.all()    #多對多
    p1.book_set.all()    #一對多


=============自定義中介模型方法===================================================    
中介模型add、create 、remove方法不可用。可是clear() 方法倒是可用的,它能夠清空某個實例全部的多對多關係。

 

 3、使用原始SQL語句

 Django提供兩種方法使用原始SQL進行查詢:一種是使用Manager.raw()方法,進行原始查詢並返回模型實例;另外一種直接執行自定義的SQL語句。

 一、使用Manager.raw()方法

Manager.raw(raw_query, params=None, translations=None)
    raw_query         SQL查詢語句。
    params             查詢條件參數,是list或者dict
    translations    字段映射表,是一個dict。
Manager.raw()將查詢結果映射到類字段,默認狀況下映射到同名字段。返回結果是一個RawQuerySet。
若是在其餘的表中有一些Author數據,你能夠很容易地把它們映射成Author實例。

手動指定字段映射字典。
    方法一:使用AS,其餘字段自動應設至Author表中的同名字段。
    na=Author.objects.raw("select name AS newname, id  from otest_author")
    >>> na[0]
    <Author_Deferred_name: 蒼松>
.
    方法二:使用translations
    name_map={"name":"newname}
    na=Author.objects.raw("select * from otest_author",translations=name_map)


params參數防止SQL注入
    方法一:使用list
    >>> na=Author.objects.raw("select * from otest_author where id =%s",[id])
    >>> na[0]
    <Author: 蒼松>
    
    方法二:使用dict
    注意:SQLite後端不支持字典,你必須以列表的形式傳遞參數。
    字典使用%(key)s佔位符(key替換成字典中相應的key值)
    p_dict={"id":1}
    na=Author.objects.raw("select * from otest_author where id =%(id)s",p_dict)

2.直接執行自定義的SQL

有時Manager.raw()方法並不十分好用,你不須要將查詢結果映射成模型,或者你須要執行UPDATE、 INSERT以及DELETE查詢。

#單數據庫
from django.db import connection
def my_custom_sql(self):
    cursor = connection.cursor()
    cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    row = cursor.fetchone()
   connection.close()
return row #多數據庫 from django.db import connections cursor = connections['my_db_alias'].cursor() # Your code here... 默認狀況下,Python DB API會返回不帶字段的結果,這意味着你獲得的是一個列表,而不是一個字典。 def dictfetchall(cursor): "Returns all rows from a cursor as a dict" desc = cursor.description return [ dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall() ] >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2"); >>> cursor.fetchall() ((54360982L, None), (54360880L, None)) >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2"); >>> dictfetchall(cursor) [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]

 

4、分組和聚合

Avg        平均值
Count(expression, distinct=False)    計算個數。若是distinct=True,Count將只計算惟一的值。默認值爲False。
Max        最大值
Min        最小值
Sum        求和
方法一:使用annotate方法,先分組(group by)再聚合
    from django.db.models import Count, Min, Max, Sum,Avg
    >>> Book.objects.values('publisher').annotate(counts_num=Count("*"))
    [{'publisher': 1, 'counts_num': 2}, {'publisher': 3, 'counts_num': 1}]
    
    >>> Book.objects.values('publisher').annotate(Avg("price"))
    [{'publisher': 1, 'price__avg': 12.5}, {'publisher': 3, 'price__avg': 11.0}]    #獲得分組的多個值列表
    使用values('publisher')進行group by分組後,在使用聚合函數纔有意義。
    默認聚合名稱filedname__聚合函數名,做爲聚合字段名。

方法二:使用aggregate方法,先過濾再聚合
    Book.objects.filter(publisher_id=1).aggregate(Count("id"))
    {'id__count': 2}    #獲得單個值

 

參考文檔:  http://python.usyiyi.cn/django/index.html中文翻譯1.8.2版中文很差的同窗能夠看這個 
相關文章
相關標籤/搜索