Django模型model

前言

  • 根據(jù)前幾篇文章的分享已經(jīng)了解djangoWeb開發(fā)一般步驟為:
    • 創(chuàng)建虛擬環(huán)境
    • 安裝django
    • 創(chuàng)建項目
    • 創(chuàng)建應(yīng)用
    • 在model.py中創(chuàng)建模型類
    • 定義視圖
    • 配置url
    • 創(chuàng)建模板

1. ORM簡介

  • MVC框架中有一個重要的部分,就是ORM愿卒,它實現(xiàn)了數(shù)據(jù)模型與數(shù)據(jù)庫的解耦,即數(shù)據(jù)模型的設(shè)計不需要依賴于特定的數(shù)據(jù)庫雕凹,通過簡單的配置就可以輕松更換數(shù)據(jù)庫
  • ORM是“對象-關(guān)系-映射”的簡稱,主要任務(wù)是:
    • 根據(jù)對象的類型生成數(shù)據(jù)庫表結(jié)構(gòu)
    • 將對象政冻、列表的操作枚抵,轉(zhuǎn)換為sql語句
    • 將sql查詢到的結(jié)果轉(zhuǎn)換為對象、列表
  • Django中的模型包含存儲數(shù)據(jù)的字段和約束明场,對應(yīng)著數(shù)據(jù)庫中唯一的表


    ORM.png

2. 使用MySql數(shù)據(jù)庫

  • 在虛擬環(huán)境中安裝mysql包

    pip install mysql-python

  • 在mysql中創(chuàng)建數(shù)據(jù)庫

    create databases test charset=utf8

  • 打開settings.py文件汽摹,修改DATABASES項

    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'test',
    'USER': '用戶名',
    'PASSWORD': '密碼',
    'HOST': '數(shù)據(jù)庫服務(wù)器ip,本地可以使用localhost',
    'PORT': '端口苦锨,默認為3306',
    }
    }

3. Django模型類開發(fā)流程

  • 在models.py中定義模型類逼泣,要求繼承自models.Model
  • 把應(yīng)用加入settings.py文件的installed_app項
  • 生成遷移文件
  • 執(zhí)行遷移生成表
  • 使用模型類進行CRUD操作

4. 定義模型類

  • 在模型中定義屬性,會生成數(shù)據(jù)庫表中的字段
  • django根據(jù)屬性的類型確定以下信息:
    • 當前選擇的數(shù)據(jù)庫支持字段的類型
    • 渲染管理表單時使用的默認html控件
    • 在管理站點最低限度的驗證
  • django會為表增加自動增長的主鍵列舟舒,每個模型只能有一個主鍵列拉庶,如果使用選項設(shè)置某屬性為主鍵列后,則django不會再生成默認的主鍵列
  • 屬性命名限制
    • 不能是python的保留關(guān)鍵字
    • 由于django的查詢方式秃励,不允許使用連續(xù)的下劃線

5. 定義模型屬性

  • 定義屬性時氏仗,需要字段類型
  • 字段類型被定義在django.db.models.fields目錄下,為了方便使用莺治,被導(dǎo)入到django.db.models中
  • 使用方式
    • 導(dǎo)入from django.db import models
    • 通過models.Field創(chuàng)建字段類型的對象廓鞠,賦值給屬性
  • 對于重要數(shù)據(jù)都做邏輯刪除帚稠,不做物理刪除谣旁,實現(xiàn)方法是定義isDelete屬性,類型為BooleanField滋早,默認值為False

6. 定義字段類型

  • TimeField:使用Python的datetime.time實例表示的時間榄审,參數(shù)同DateField
  • DateTimeField:使用Python的datetime.datetime實例表示的日期和時間,參數(shù)同DateField
  • FileField:一個上傳文件的字段
  • ImageField:繼承了FileField的所有屬性和方法杆麸,但對上傳的對象進行校驗搁进,確保它是個有效的image
  • AutoField:一個根據(jù)實際ID自動增長的IntegerField,通常不指定
    • 如果不指定昔头,一個主鍵字段將自動添加到模型中
  • BooleanField:true/false 字段饼问,此字段的默認表單控制是CheckboxInput
  • NullBooleanField:支持null、true揭斧、false三種值
  • CharField(max_length=字符長度):字符串莱革,默認的表單樣式是 TextInput
  • TextField:大文本字段,一般超過4000使用,默認的表單控件是Textarea
  • IntegerField:整數(shù)
  • DecimalField(max_digits=None, decimal_places=None):使用python的Decimal實例表示的十進制浮點數(shù)
  • DecimalField.max_digits:位數(shù)總數(shù)
  • DecimalField.decimal_places:小數(shù)點后的數(shù)字位數(shù)
  • FloatField:用Python的float實例來表示的浮點數(shù)
  • DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date實例表示的日期
    • 參數(shù)DateField.auto_now:每次保存對象時盅视,自動設(shè)置該字段為當前時間捐名,用于"最后一次修改"的時間戳,它總是使用當前日期闹击,默認為false
    • 參數(shù)DateField.auto_now_add:當對象第一次被創(chuàng)建時自動設(shè)置當前時間镶蹋,用于創(chuàng)建的時間戳,它總是使用當前日期赏半,默認為false
    • 該字段默認對應(yīng)的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日歷控件贺归,和一個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
    • auto_now_add, auto_now, and default 這些設(shè)置是相互排斥的断箫,他們之間的任何組合將會發(fā)生錯誤的結(jié)果

7. 模型類中字段選項

  • 通過字段選項牧氮,可以實現(xiàn)對字段的約束
  • 在字段對象時通過關(guān)鍵字參數(shù)指定
  • null:如果為True,Django 將空值以NULL 存儲到數(shù)據(jù)庫中瑰枫,默認值是 False
  • blank:如果為True踱葛,則該字段允許為空白,默認值是 False
  • 對比:null是數(shù)據(jù)庫范疇的概念光坝,blank是表單驗證證范疇的
  • db_column:字段的名稱尸诽,如果未指定,則使用屬性的名稱
  • db_index:若值為 True, 則在表中會為此字段創(chuàng)建索引
  • default:默認值
  • primary_key:若為 True, 則該字段會成為模型的主鍵字段
  • unique:如果為 True, 這個字段在表中必須有唯一值

8. 模型類之間關(guān)系

  • 關(guān)系的類型包括

    • ForeignKey:一對多盯另,將字段定義在多的端中
    • ManyToManyField:多對多性含,將字段定義在兩端中
    • OneToOneField:一對一,將字段定義在任意一端中
  • 可以維護遞歸的關(guān)聯(lián)關(guān)系鸳惯,使用'self'指定商蕴,就是“自關(guān)聯(lián)”

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

    mytestinfo.testinfo_set.all()

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

    testinfo.mytestinfo

  • 訪問id:對象.屬性_id

    testinfo.mytest_id

9. 模型類中定義類Meta

  • 元信息db_table:定義數(shù)據(jù)表名稱,推薦使用小寫字母芝发,數(shù)據(jù)表的默認名稱

    <應(yīng)用名稱>_<模型類名稱>

  • ordering:對象的默認排序字段绪商,獲取對象的列表時使用,接收屬性構(gòu)成的列表

    class TestInfo(models.Model):
    class Meta():
    ordering = ['id']

  • 字符串前加-表示倒序辅鲸,不加-表示正序

    class TestInfo(models.Model):
    class Meta():
    ordering = ['-id']

10. 模型類的管理器

  • objects:是Manager類型的對象格郁,用于與數(shù)據(jù)庫進行交互

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

  • 支持明確指定模型類的管理器

    class BookInfo(models.Model):
    books = models.Manager()

  • 當為模型類指定管理器后独悴,django不再為模型類生成名為objects的默認管理器

  • 管理器是Django的模型進行數(shù)據(jù)庫的查詢操作的接口例书,Django應(yīng)用的每個模型都擁有至少一個管理器

  • 自定義管理器類主要用于兩種情況

    • 向管理器類中添加額外的方法創(chuàng)建管理器對象保存數(shù)據(jù)到數(shù)據(jù)庫

      class TestInfoManager(models.Manager):
      def create_test(self, title, update):
      test = self.model()
      test.isDelete = False
      return test

      class TestInfo(models.Model):
      tests = TestInfoManager()
      方法調(diào)用:book=TestInfo. tests.create_ test("abc",datetime(1980,1,1))
      保存:test.save()

    • 修改管理器返回的原始查詢集:重寫get_queryset()方法

      class TestInfoManager(models.Manager):
      def get_queryset(self):

      return super(TestInfoManager, self).get_queryset().filter(isDelete=False)
      class TestInfo(models.Model):
      tests = TestInfoManager()

  • 當創(chuàng)建對象時,django不會對數(shù)據(jù)庫進行讀寫操作

  • 在管理器的方法中刻炒,可以通過self.model來得到它所屬的模型類

  • 調(diào)用save()方法才與數(shù)據(jù)庫交互决采,將對象保存到數(shù)據(jù)庫中

  • 使用關(guān)鍵字參數(shù)構(gòu)造模型對象很麻煩,推薦使用下面的兩種之式

  • 說明: _init _方法已經(jīng)在基類models.Model中使用坟奥,在自定義模型中無法使用

  • 在模型類中增加一個類方法保存數(shù)據(jù)到數(shù)據(jù)庫

    class BookInfo(models.Model):
    @classmethod
    def create(cls, title):
    test = cls(btitle=title)
    test.isDelete = False
    return test
    引入時間包:from datetime import *
    調(diào)用:test=TestInfo.create("hello");
    保存:test.save()

  • DoesNotExist:在進行單個查詢時树瞭,模型的對象不存在時會引發(fā)此異常暂幼,結(jié)合try/except使用

  • 實例方法

    • str (self):重寫object方法,此方法在將對象轉(zhuǎn)換成字符串時會被調(diào)用
    • delete():將模型對象從數(shù)據(jù)表中刪除

11. 模型類的查詢

  • 查詢集表示從數(shù)據(jù)庫中獲取的對象集合
  • 查詢集可以含有零個移迫、一個或多個過濾器
  • 過濾器基于所給的參數(shù)限制查詢的結(jié)果
  • 從Sql的角度旺嬉,查詢集和select語句等價,過濾器像where和limit子句
  • 接下來主要討論如下知識點
    • 查詢集
    • 字段查詢:比較運算符厨埋,F(xiàn)對象邪媳,Q對象
(1)模型類查詢集合
  • 在管理器上調(diào)用過濾器方法會返回查詢集

  • 查詢集經(jīng)過過濾器篩選后返回新的查詢集,因此可以寫成鏈式過濾

  • 惰性執(zhí)行:創(chuàng)建查詢集不會帶來任何數(shù)據(jù)庫的訪問荡陷,直到調(diào)用數(shù)據(jù)時雨效,才會訪問數(shù)據(jù)庫

  • 何時對查詢集求值:迭代,序列化废赞,與if合用

  • 返回查詢集的方法徽龟,稱為過濾器,管理器對象方法有all()唉地、filter()据悔、exclude()、order_by()耘沼、values()

  • 返回單個值的方法

    • get():返回單個滿足條件的對象
    • 如果未找到會引發(fā)"模型類.DoesNotExist"異常
    • 如果多條被返回极颓,會引發(fā)"模型類.MultipleObjectsReturned"異常
    • count():返回當前查詢的總條數(shù)
    • first():返回第一個對象
    • last():返回最后一個對象
    • exists():判斷查詢集中是否有數(shù)據(jù),如果有則返回True
  • 限制查詢集群嗤,如果獲取一個對象菠隆,直接使用[0]

  • 模型查詢集的緩存

    • 這構(gòu)成了兩個查詢集,無法重用緩存狂秘,每次查詢都會與數(shù)據(jù)庫進行一次交互骇径,增加了數(shù)據(jù)庫的負載

      print([e.title for e in Entry.objects.all()])
      print([e.title for e in Entry.objects.all()])

    • 兩次循環(huán)使用同一個查詢集,第二次使用緩存中的數(shù)據(jù)

      querylist=Entry.objects.all()
      print([e.title for e in querylist])
      print([e.title for e in querylist])

  • 何時查詢集不會被緩存:當只對查詢集的部分進行求值時會檢查緩存者春,但是如果這部分不在緩存中破衔,那么接下來查詢返回的記錄將不會被緩存,這意味著使用索引來限制查詢集將不會填充緩存碧查,如果這部分數(shù)據(jù)已經(jīng)被緩存运敢,則直接使用緩存中的數(shù)據(jù)

  • 比較運算符:表示兩個下劃線校仑,左側(cè)是屬性名稱忠售,右側(cè)是比較類型

    • exact:表示判等,大小寫敏感迄沫;如果沒有寫“ 比較運算符”稻扬,表示判等

      filter(isDelete=False)

    • contains:是否包含,大小寫敏感

      exclude(btitle__contains='傳')

    • startswith羊瘩、endswith:以value開頭或結(jié)尾泰佳,大小寫敏感

      exclude(btitle__endswith='傳')

    • isnull盼砍、isnotnull:是否為null

      filter(btitle__isnull=False)

    • 在前面加個i表示不區(qū)分大小寫,如iexact逝她、icontains浇坐、istarswith、iendswith

    • in:是否包含在范圍內(nèi)

      filter(pk__in=[1, 2, 3, 4, 5])

    • gt黔宛、gte近刘、lt、lte:大于臀晃、大于等于觉渴、小于、小于等于

      filter(id__gt=3)

    • year徽惋、month案淋、day肖方、week_day展懈、hour叛薯、minute奶是、second:對日期間類型的屬性進行運算

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

    • 跨關(guān)聯(lián)關(guān)系的查詢:處理join查詢

      語法:模型類名 <屬性名> <比較>
      注:可以沒有__<比較>部分俭识,表示等于弦牡,結(jié)果同inner join
      可返向使用旨涝,即在關(guān)聯(lián)的兩個模型中都可以使用
      filter(heroinfo__hcontent__contains='八')

    • 查詢的快捷方式:pk,pk表示primary key白华,默認的主鍵是id

      filter(pk__lt=6)

(2)聚合函數(shù)
  • 使用aggregate()函數(shù)返回聚合函數(shù)的值
  • 函數(shù):Avg,Count贩耐,Max,Min潮太,Sum

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

  • count的一般用法:

    count = list.count()

(3)F對象
  • 可以使用模型的字段A與字段B進行比較,如果A寫在了等號的左邊铡买,則B出現(xiàn)在等號的右邊更鲁,需要通過F對象構(gòu)造

    list.filter(read__gte=F('commet'))

  • django支持對F()對象使用算數(shù)運算

    list.filter(read__gte=F('commet') * 2)

  • F()對象中還可以寫作“模型類__列名”進行關(guān)聯(lián)查詢

    list.filter(isDelete=F('testinfo__isDelete'))

  • 對于date/time字段奇钞,可與timedelta()進行運算

    list.filter(update__lt=F('update') + timedelta(days=1))

(3)Q對象
  • 過濾器的方法中關(guān)鍵字參數(shù)查詢,會合并為And進行

  • 需要進行or查詢景埃,使用Q()對象

  • Q對象(django.db.models.Q)用于封裝一組關(guān)鍵字參數(shù)媒至,這些關(guān)鍵字參數(shù)與“比較運算符”中的相同

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

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

  • 當操作符應(yīng)用在兩個Q對象時,會產(chǎn)生一個新的Q對象

    list.filter(pk_ lt=6).filter(bcommet gt=10)
    list.filter(Q(pk
    lt=6) | Q(bcommet _gt=10))

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

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

  • 可以使用&|~結(jié)合括號進行分組拒啰,構(gòu)造做生意復(fù)雜的Q對象

  • 過濾器函數(shù)可以傳遞一個或多個Q對象作為位置參數(shù)驯绎,如果有多個Q對象,這些參數(shù)的邏輯為and

  • 過濾器函數(shù)可以混合使用Q對象和關(guān)鍵字參數(shù)谋旦,所有參數(shù)都將and在一起条篷,Q對象必須位于關(guān)鍵字參數(shù)的前面

12. 模型自關(guān)聯(lián)

  • 對于地區(qū)信息,屬于一對多關(guān)系蛤织,使用一張表赴叹,存儲所有的信息
  • 類似的表結(jié)構(gòu)還應(yīng)用于分類信息,可以實現(xiàn)無限級分類

    class AreaInfo(models.Model):
    atitle = models.CharField(max_length=20)
    aParent = models.ForeignKey('self', null=True, blank=True)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末指蚜,一起剝皮案震驚了整個濱河市乞巧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摊鸡,老刑警劉巖绽媒,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異免猾,居然都是意外死亡是辕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門猎提,熙熙樓的掌柜王于貴愁眉苦臉地迎上來获三,“玉大人,你說我怎么就攤上這事锨苏「斫蹋” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵伞租,是天一觀的道長贞谓。 經(jīng)常有香客問我,道長葵诈,這世上最難降的妖魔是什么裸弦? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮作喘,結(jié)果婚禮上理疙,老公的妹妹穿的比我還像新娘。我一直安慰自己徊都,他們只是感情好沪斟,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布暇矫。 她就那樣靜靜地躺著,像睡著了一般李根。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粤攒,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音夯接,去河邊找鬼。 笑死盔几,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的逊拍。 我是一名探鬼主播际邻,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼世曾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轮听,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕊程,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藻茂,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年辨赐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帆焕。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖叶雹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情折晦,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布满着,位于F島的核電站,受9級特大地震影響风喇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜魂莫,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秽誊。 院中可真熱鬧,春花似錦锅论、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炫狱。三九已至,卻和暖如春视译,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酷含。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留椅亚,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓呀舔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霜瘪,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容