[Python] Django框架入門2——深入模型

 

說明:

  本文主要深入瞭解模型(models.py),涉及ORM簡介、模型定義、模型成員、模型查詢、自連接等。需要一定基礎,可以先走一走基本入門流程。

  附錄一使用mysql數據庫,附錄二Django開發流程。

目錄:

  一、ORM簡介

    ORM簡介 

  二、模型定義

    1、基本模型

    2、字段類型

    3、字段選項

    4、關係

    5、元選項

  三、模型成員

    1、查詢

    2、Django默認的管理器

    3、自定義管理器

  四、模型查詢

    1、查詢集

    2、字段查詢

    3、

  五、自連接

  附錄一:使用mysql

  附錄二:Django開發流程

  

一、ORM簡介(引用,詳情請查閱相關文檔)

  ORM(Object Relational Mapping)即是"對象-關係-映射"的簡稱,是MVC框架一個重要的部分(Django也支持ORM),它實現了數據模型與數據庫的解耦,即數據模型的設計不需要依賴於特定的數據庫,通過簡單的配置可以輕鬆更換數據庫。

  ORM的作用:

    根據對象的類型生成表結構

    將對象、列表的操作,轉換成sql語句

    將sql查詢到的結果轉換爲對象、列表

  使用ORM主要方便開發人員,極大減輕開發人員的工作量,避免手寫sql語句出現的各種問題。

  Django中的模型包含存儲的字段和約束,對應着數據庫中唯一的表。

  

 

 

 

二、模型定義

  1、基本的模型  

 1 from django.db import models
 2 
 3 
 4 class BookInfo(models.Model):
 5     """
 6         圖書類 => 圖書表(booktest_bookinfo)
 7     """
 8     # 圖書標題 => varchar(20)
 9     btitle = models.CharField(max_length=20)
10     # 發佈日期 => datetime
11     bpub_date = models.DateTimeField()
12     # 閱讀數 => int(11)
13     bread = models.IntegerField(default=0)
14     # 評論數 => int(11)
15     bcomment = models.IntegerField(default=0)
16     # 是否刪除 => tinyint
17     isDelete = models.BooleanField(default=False)
18 
19     def __str__(self):
20         return self.btitle
21 
22 
23 class HeroInfo(models.Model):
24     """
25         英雄類 => 英雄表(booktest_heroinfo)
26     """
27     # 英雄名字 => varchar(20)
28     hname = models.CharField(max_length=20)
29     # 性別 => tinyint
30     hgender = models.BooleanField(default=True)
31     # 簡介 => varchar(1000)
32     hcontent = models.CharField(max_length=1000)
33     # 是否刪除 => tinyint
34     isDelete = models.BooleanField(default=False)
35     # 外鍵 => int(11)
36     hbook = models.ForeignKey(BookInfo)  # 外鍵

    說明:

      定義屬性時,需要字段類型

      字段類型被定義在django.db.models.fields目錄下,爲了方便使用,被導入到django.db.models中

      使用方式:見上面代碼

      對於重要數據都做邏輯刪除,不做物理刪除,實現方法是定義isDelete屬性,類型爲BooleanField,默認值爲False

        

  2、字段類型(引用)

    表單控制是指在django管理站點的前端顯示。

    AutoField:根據ID自動增長的IntegerField,一般無需指定,django會自動添加到模型中,數據庫類型爲 int(11)。

    BooleanFidld:true/false字段,此字段的默認表單控件是CheckboxInput,數據庫類型爲 tinyint。

    NullBooleanField:支持null、true、false三種值,數據庫類型爲 tinyint。

    CharField(max_length=字符長度):字符串,默認的表單控件是TextInput,數據庫類型爲 varchar(字符長度)。

    TextField:大文本字段,一般字符長度超過4k使用,默認的表單控件是Textarea,數據庫類型爲 varchar(字符長度)。

    IntegerField:整數,數據庫類型爲 int。

    DecimalField(max_digits=None, decimal_places=None):使用python的Decimal實例表示的十進制浮點數,數據庫類型爲 decimal(P, D):

      DecimalField.max_digits:位數總數

         DecimalField.decimal_places:小數點後的數字位數。

    FloatField:使用python的float實例來標識的浮點數。

    DateField([auto_now=False, auto_noew_add=False]):使用pyhton的datetime.date實例表示日期。

      參數auto_now:每次保存對象時,自動設置該字段爲當前時間,用於保存"最後一次修改"的時間戳,他總是使用當前的日期,默認爲false

      參數auto_now_add:當對象第一次被創建時自動設置當前時間,用於保存創建的時間戳,它總是使用當前日期,默認爲false

      該字段默認對應的表單控件是TextInput

      auto_now、auto_now_add、default 這些設置是相互排斥的,他們之間任何組合將會發生錯誤的結果 。

    TimeField:使用python的datetime.time實例表示的時間,參數同DatEField。

    DateTimeField:使用python的datetime.datetime實例表示的日期和時間,參數同DateField

    FileField:一個上傳文件的字段,一般不會把文件保存在數據庫中,建議保存文件上傳的路徑。

    ImageField:繼承FieldField的所有屬性和方法,當對上傳的對象進行校驗,確保上傳是有些的image。

 

  3、字段選項

    使用:title = models.CharFidle(null=True)

    null:如果爲True,Django將空值以NULL存儲到數據庫中,默認值是False。

    blank:如果爲True,則該字段允許爲空,默認值是False。

    null與blank對比:null是數據庫範疇的概念,blank是表單驗證範疇的。

    db_column:字段的名稱,如果爲指定,則使用屬性的名稱。

    db_index:如果爲True,則在表中會爲此字段創建索引

    default:默認值。

    primary_key:如果爲True,則該字段會成爲模型的主鍵字段。

    unique:如果爲True,表示這個字段在表中必須有唯一值。

 

  4、關係

    關係的類型有如下:

      ForeignKey:一對多,將字段定義在多的端中(如上面基本模型的代碼)。

      ManyToManyField:多對多,將字段定義在兩端中

      OneToOneField:一對一,將字段定義在任意一端中。

    訪問方式:

      用一訪問多:對象.模型類小寫_set 

        bookinfo.heroinfo_set

      用一訪問一:對象.模型類小寫

        heroinfo.bookinfo

        heroinfo.book_id

  

  5、元選項

    在模型類中定義類Meta,用於設置元信息    

1 class BookInfo(models.Model):
2     # 元選項
3     class Meta:
4         # 數據表名
5         db_table = 'bookinfo'
6         # 對象默認排序字段,正序
7         ordering = ['id']
8         # ordering = ['-id']    # 倒序

 

 

三、模型成員

  1、查詢數據

     book_list = BookInfo.objects.all() 

  

  2、Django默認的管理器

    objects:是Manager類型的對象,用於與數據庫進行交互。

    當定義模型時沒有指定管理器,則Django會爲模型類提供一個名爲objects的管理器。

    支持明確指定管理器(如果自己指定manager,django不再爲模型類生成名爲objects的默認管理器):   

1 class BookInfo(models.Model):
2     manager1 = models.Manager()

 

  3、自定義管理器

    管理器是Django的模型進行數據庫的查詢操作的接口,Django應用的每個模型都擁有至少一個管理器。

    自定義管理器主要用於以下兩種情況:

      情況一:修改管理器返回的原始查詢集:重寫get_query_set()方法。

      情況二:向管理器中添加額外的方法

    代碼如下(manager2就是自定義的管理器):

 1 class BookInfoManager(models.Manager):
 2     """
 3         自定義管理器
 4     """
 5     # 情況一:更改默認查詢結果,只查未刪除的數據
 6     def get_queryset(self):
 7         return super(BookInfoManager, self).get_queryset().filter(isDelete=False)
 8 
 9     # 情況二:定義模型類的創建方法
10     def create(cls, btitle, bpub_date):
11         b = BookInfo()
12         b.btitle = btitle
13         b.bpub_date = bpub_date
14         b.bread = 0
15         b.bcomment = 0
16         b.isDelete = False
17         return b
18 
19 
20 class BookInfo(models.Model):
21     btitle = models.CharField(max_length=20)
22     bpub_date = models.DateTimeField()
23     bread = models.IntegerField(default=0)
24     bcomment = models.IntegerField(default=0)
25     isDelete = models.BooleanField(default=False)
26 
27     def __str__(self):
28         return self.btitle
29 
30     # 管理器
31     manager1 = models.Manager()
32     manager2 = BookInfoManager()    

 

     情況一的測試結果如下:

      

        

 

 

     情況二的測試結果如下(簡化創建對象的過程:new->賦值->save):

       

        

四、模型查詢

  1、查詢集

    在管理器上調用過濾器方法返回查詢集。

    查詢集經過過濾篩選後返回信的查詢集,因此可以寫成鏈式過濾。

    惰性執行:創建查詢集不會帶來任何數據的訪問,直到調用數據的時候(迭代、序列號、與if合用),纔會訪問數據庫。

    返回查詢集的方法,稱爲過濾器:all()filter()exclude()order_by()values()

    寫法:manager.filter(鍵1=值1, 鍵2=值2) => manager.filter(鍵1=值1).filter(鍵2=值2)

      

 

    返回單個值的方法:

      get():返回單個滿足添加的對象

        如果未找到會引發"模型類 DoesNotExist"異常

        如果多條被返回,會引發"模型類 MultipleObjectsReturn"異常

      count():返回當前查詢的總條數

      first():返回第一個對象

      last():返回最後一個對象

      exists():判斷查詢集中是否有數據,有則返回True

    

    限制查詢集:

      查詢集返回列表,可以使用下標的方式進行限制,等同於sql中limit和offset子句

      注意:不支持負數索引

      如果下標返回一個新的查詢集,不會立刻執行查詢

      如果獲取一個對象,直接使用[0],等同於[0:1].get()。但是如果沒有數據,[0]引發IndexError異常,[0:1].get()引發DoesNotExist異常。

      

    查詢集的緩存

      每個查詢集都包含一個緩存來最小化對數據庫的訪問。

      在新建的查詢集中,緩存爲空,首次對查詢集求值時,會發生數據庫查詢,Django會將查詢的結果存在查詢集的緩存中,並返回請求的結果,接下來對查詢集求值將重用緩存的結果。

      情況一:構建兩個查詢集,無法重用緩存,每次查詢都會與數據庫進行交互,增加數據庫的負載

      

      情況二:兩次循環使用同一個查詢集,第二次使用緩存中的數據

        

      何時查詢集不會被緩存:當只對查詢集的部分進行求值時,會檢查緩存,但是如果這部分不再緩存中,那麼接下來查詢返回的機率將不會被緩存,這意味着使用索引來限制查詢集將不會填充緩存,如果這部分數據已經被緩存,則直接使用緩存中的數據。

 

1 query = BookInfo.objects.all()
2 for each in query    # 緩存
3 for each in query[0,10] # 不緩存
4 # 使用子集不緩存

 

  2、字段查詢:比較運算符,F對象,Q對象

    實現where子句,作爲方法filter()、exclude()、get()的參數。

    語法:屬性名__比較運算符=值,__ 表示兩個下劃線,左側是屬性名稱,右側是比較類型。

    對於外鍵:使用 "屬性名__id" 表示外鍵原始值

    轉義:like語句中使用%與_,匹配數據中的%與_,在過濾器中直接寫:

      filter(title__contains="%")  => WHERE `title` LIKE '%\%%'

    

    比較運算符

      exact:表示判等,大小寫敏感,如果沒有寫 “比較運算符”,表示判等:

        filter(isDelete=False) => WHERE `isDelete` = 0

      contains:是否包含。大小寫敏感:

        exclude(btitle__contains='傳') => WHERE `btitle`  LIKE '%傳%'

      startswhitendswith:以value開頭或結尾,大小寫敏感:

        exclude(btitle__endswith='傳') => WHERE `btitle` LIKE '%傳'

        exclude(btitle__startswith='傳') => WHERE `btitle` LIKE '傳%'

      isnullisnotnull:是否爲null:

        filter(btitle__isnull=False) => WHERE `btitle` != null

      在前面加 i 表示不區分大小寫,如:iexact、icontains、istartswith、iendswith

    

      in:是否包含在範圍內:

        filter(pk__in=[1,2,3]) => WHERE `id`  IN (1, 2, 3)

      gtgteltlte:大於、大於等於、小於、小於等於

        filter(id__gt=3) => WHERE `id` > 3

        filter(id__lte=5) => WHERE `id` <= 5

      yearmonthdayweek_dayhourminutesecond:對日期時間類型的屬性進行運算:

        filter(bpub_date__year=1980)  

        filter(bpub_date__gt=date(1980, 12, 31))

      跨關係的查詢:處理join查詢:

        filter(heroinfo__hcontent__contains='八') => SELECT * FROM `bookinfo` JOIN `heroinfo` ON `bookinfo`.`id`=`heroinfo`.`hbook` WHERE `heroinfo`.`hcontent` LIKE '%八%'

      聚合函數

        使用aggregate()函數返回聚合函數的值

        函數:Avg、Count、Max、Min、Sum

from django.db.models import Max
maxDate = BookInfo.objects.aggregate(Max('bpub_date'))

 

        count的一般用法:count = list.count()

      

      F對象:構建等號右側字段:

        可以使用模型的字段A與字段B進行比較,如果A在等號左側,則B出現在等號的右側時需要通過F對象構造:

          list.filter(bread__gt=F('bcomment')) => WHERE `bread` > `bcomment`

        Django支持對F對象使用算數運算:

          list.filter(bread__gte=F('bcomment')) => WHERE `bread` >= `bcomment` * 3

        F()對象還可以寫作“模型類__列名”進行關聯查詢:

          list.filter(isDelete=F('heroinfo__isDelete')) => WHERE `bookinfo`.`isDelete` = `heroinfo`.`isDelete`

        對於date/time字段,可與timedelta()進行運算:

          list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

      

      Q對象:處理邏輯或:

        過濾器方法中關鍵字參數查詢,會合併爲And進行查詢。

        需要進行or查詢,使用Q對象

        Q對象(django.db.models.Q)用於封裝一組關鍵字參數,這些關鍵字參數與“比較運算符”中的相同  

from django.db.models import Q
list.filter(Q(pk__lt=6))

 

         Q對象可以使用&(and)、|(or)操作符組合起來

         當操作符應用在兩個Q對象時,會產生一個新的Q對象

 list.filter(pk__lt=6).filter(bcomment__gt=10) # WHERE `id` < 6 AND `bcomment` > 10
 list.filter(Q(pk__lt=6) | Q(bcomment__gt=10))  # WHERE `id` < 6 OR `bcomment` > 10

 

        使用~(not)操作符在Q對象前表示取反 

           list.filter(~Q(pk__lt=6)) 

        

        可以使用&|~結合括號進行分組,構造複雜的Q對象

        過濾函數可以傳遞一個或多個Q對象作爲位置參數,如果有多個Q對象,這些參數的邏輯爲and

        過濾器函數可以混合使用Q對象和關鍵字參數,所有參數都將And在一起,Q對象必須位於關鍵字參數的前面。

 

五、自連接

  自連接主要應用於無限級分類等。

1 class AreaInfo(models.Model):
2     atitle = models.CharFields(max_lenth=20)
3     aParent = mdoels.ForeignKey('self', null=True, blank=True)

 

  訪問關聯對象:

    上級:area.aParent

    下級:area.areainfo_set.all()

 

附錄一:使用mysql數據庫

  1、安裝插件:python-mysql 或 mysqlclient

    我的電腦安裝的是python3.5,通過wheel安裝mysqlclient,下載地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient

  2、修改配置文件

      

 

 附錄二:Django開發流程

  1、創建項目:執行指令:django-admin startproject [項目名]

  2、進入項目目錄,創建應用:執行指令:python manager.py startapp [應用名]

  3、進入應用目錄,在models.py中定義模型類,要求繼承自models.Model

  4、把應用加入settings.py文件中的installed_app項中

  5、生成遷移文件,執行指令:python manager.py makemigrations

  6、執行遷移生成表,執行指令:python manager.py migrate

  7、使用模型類進行crud操作

 

  *、使用數據庫生成模型類

    python manager.py inspectdb > booktest/models.py

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章