Models#1

  • model是Django中的數(shù)據(jù)模型
    • 每個(gè)model都是繼承自django.db.models.Model的子類
    • 每個(gè)model都映射一個(gè)數(shù)據(jù)表
    • model中的每個(gè)類屬性對(duì)應(yīng)著數(shù)據(jù)表中的一列
    • django支持ORM
  • 創(chuàng)建model并進(jìn)行migrate后
    • Django會(huì)自動(dòng)生成表名(可以自定義
    • Django會(huì)自動(dòng)增加主鍵一列(可以自定義)
    • Django會(huì)根據(jù)不同數(shù)據(jù)庫(kù)創(chuàng)建不同的SQL語(yǔ)句
  • Field中的常見選項(xiàng)
    • null:允許該列數(shù)據(jù)為空(默認(rèn)為False)
    • blank:主要用于是否允許表單為空(默認(rèn)為False)
    • choices:為一個(gè)Field提供可選項(xiàng)(并且默認(rèn)生成的表單為一個(gè)選項(xiàng))
      from django.db import models
      
      class Person(models.Model):
          # choices的對(duì)象是一個(gè)可迭代對(duì)象移层,其元素為‘含有兩個(gè)元素的元組’
          SHIRT_SIZES = (
              ('S', 'Small'),
              ('M', 'Medium'),
              ('L', 'Large'),
          )
          name = models.CharField(max_length=60)
          shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
        
      # choice API
      >>> p = Person(name="Fred Flintstone", shirt_size="L")
      >>> p.save()
      >>> p.shirt_size
      'L'
      >>> p.get_shirt_size_display()   # get_FOO_display()方法可以顯示具體內(nèi)容
      'Large'
      
    • default:既可以是一個(gè)數(shù)值對(duì)象墓贿,也可以是一個(gè)可調(diào)用對(duì)象
    • help_text:在生成的表單中展示‘幫助’信息
    • primary_key:將某一列設(shè)置為主鍵(該列變?yōu)橹蛔x)竖配;默認(rèn)為False,即Django會(huì)自動(dòng)創(chuàng)建一個(gè)整型主鍵
    • unique:該列中的每個(gè)數(shù)據(jù)必須獨(dú)一無(wú)二(默認(rèn)為False)
  • 自動(dòng)生成主鍵
    默認(rèn)情況下乳愉,如果不顯式指定主鍵,Django會(huì)在model中自動(dòng)添加以下屬性
    id = models.AutoField(primary_key=True)
    
  • 顯式指定列名
    對(duì)于非關(guān)系型列(即非ForeignKeyField,ManyToManyField蕾总,OneToOneField)戴尸,第一個(gè)位置參數(shù)為空時(shí)粟焊,將默認(rèn)屬性名為列名;否則使用位置參數(shù)作為列名
    對(duì)于關(guān)系型列孙蒙,需要指定位置參數(shù)以表明關(guān)聯(lián)的數(shù)據(jù)表
    # 列名為"person's first name"
    first_name = models.CharField("person's first name", max_length=30)
    
    # 列名為"first_name"
    first_name = models.CharField(max_length=30)
    
    # 關(guān)聯(lián)表為"Poll"
    poll = models.ForeignKey(
        Poll,
        on_delete=models.CASCADE,
        verbose_name="the related poll",
    )
    
  • 關(guān)聯(lián)
    • Many-to-one 關(guān)聯(lián)
      使用django.db.models.ForeignKey项棠,第一個(gè)位置參數(shù)需要指定關(guān)聯(lián)表名
    • Many-to-many 關(guān)聯(lián)
      使用django.db.models.ManyToManyField(相關(guān)的兩個(gè)表中,只需要在一個(gè)表中指定即可)
      可以顯式的創(chuàng)建many-to-many的關(guān)聯(lián)數(shù)據(jù)表
      from django.db import models
      
      class Person(models.Model):
          name = models.CharField(max_length=128)
      
          def __str__(self):              # __unicode__ on Python 2
              return self.name
      
      class Group(models.Model):
          name = models.CharField(max_length=128)
          # 通過(guò)through指定關(guān)聯(lián)表
          members = models.ManyToManyField(Person, through='Membership')
      
          def __str__(self):              # __unicode__ on Python 2
              return self.name
      
      class Membership(models.Model):
          person = models.ForeignKey(Person, on_delete=models.CASCADE)
          group = models.ForeignKey(Group, on_delete=models.CASCADE)
          date_joined = models.DateField()
          invite_reason = models.CharField(max_length=64)
      
    • One-to-one 關(guān)聯(lián)
      使用django.db.models.OneToOneField马篮,可以用于擴(kuò)展某一model
  • Meta 選項(xiàng)
    Model的Meta中保存著所有非列的屬性(比如ordering(默認(rèn)排序)沾乘、db_table(數(shù)據(jù)表名稱)等等)
    from django.db import models
    
    class Ox(models.Model):
        horn_length = models.IntegerField()
        
        # class Meta 是可選項(xiàng)
        class Meta:
            ordering = ["horn_length"]
            verbose_name_plural = "oxen"
    
  • Model 的方法
    我們可以在Model中自定義方法,也可以使用或者重載Model中已有的方法
    有兩個(gè)方法在大多數(shù)情況下需要我們自己定義
    • __ str__()
    • get_absolute_url()
      該方法告訴Django如何得到一個(gè)對(duì)象的URL(一般使用django的reverse()函數(shù))
      def get_absolute_url(self):
          from django.urls import reverse
          return reverse('people.views.details', args=[str(self.id)])
      
    重載Model中已定義的方法
    from django.db import models
    
    class Blog(models.Model):
        name = models.CharField(max_length=100)
        tagline = models.TextField()
    
        def save(self, *args, **kwargs):
            do_something()
            # 關(guān)鍵在于對(duì)Model.save()方法的繼承上浑测,另外通過(guò)使用(*args, **kwargs)參數(shù)可以自動(dòng)獲取相關(guān)參數(shù)
            super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
            do_something_else()
    

  • Model的繼承
    django中存在三種繼承
    • Abstract base classes
    • Multitable inheritance
    • Proxy models
  • Abstract base classes
    在class Meta中設(shè)置abstract = True翅阵,就可以將該model變?yōu)槌橄箢悺擃愔卸x的列屬性可以被子類所繼承而無(wú)需重新定義歪玲,且class Meta中的屬性亦會(huì)被繼承(除了abstract = True)
    Abstract base classes并不會(huì)產(chǎn)生數(shù)據(jù)表,也不能直接用于創(chuàng)建實(shí)例
    from django.db import models
    
    class CommonInfo(models.Model):
        name = models.CharField(max_length=100)
        age = models.PositiveIntegerField()
        
        # 將CommonInfo聲明為一個(gè)abc類
        class Meta:
            abstract = True
            ordering = ['name']
    
    class Student(CommonInfo):
        # Student 類自動(dòng)繼承name和age列
        home_group = models.CharField(max_length=5)
    
        class Meta: 
            # Student 類會(huì)繼承CommonInfo中的Meta的信息
            # 不過(guò)在此之前會(huì)自動(dòng)設(shè)置abstract=False(當(dāng)然也可以自己顯式地設(shè)置abstract=True從而成為abc類)
            db_table = 'student_info'
    
    為了指定子類關(guān)聯(lián)表列的relate_name掷匠,可以在abc類的關(guān)聯(lián)表列中進(jìn)行設(shè)置
    # common/models.py
    from django.db import models
    
    class Base(models.Model):
        m2m = models.ManyToManyField(
            OtherModel,
            # 若不設(shè)置related_name滥崩,則默認(rèn)為"子類名 + '_set'"
            # %(app_label)s 指代當(dāng)前應(yīng)用名稱
            # %(class)s 指代當(dāng)前類的類名
            related_name="%(app_label)s_%(class)s_related",
            related_query_name="%(app_label)s_%(class)ss",
        )
    
        class Meta:
            abstract = True
    
    # OtherModel 使用 ChildA 類時(shí)的屬性名將是'common_childa_related'
    class ChildA(Base):
        pass
    
    class ChildB(Base):
        pass
    
  • Multi-table inheritance
    父類和子類都可以生成數(shù)據(jù)表,且子類會(huì)繼承父類的類屬性(列屬性)讹语,但父類和子類是兩個(gè)不同的表
    此外钙皮,不同于abc類,子類不會(huì)繼承父類class Meta中的屬性
  • Proxy models
    Proxy model用于當(dāng)你只想為一個(gè)表增加一些方法或者M(jìn)eta屬性顽决,而不想改變?cè)璵odel的代碼時(shí)
    from django.db import models
    
    class Person(models.Model):
        first_name = models.CharField(max_length=30)
        last_name = models.CharField(max_length=30)
    
    class MyPerson(Person):
        class Meta:
            # 指定該類為Person的代理數(shù)據(jù)模型
            proxy = True
            # 在該proxy model中可以增加一個(gè)額外的Meta屬性
            odering = ['last_name']
    
        # 在該proxy model中可以增加一些額外的方法
        def do_something(self):
            # ...
            pass
    
    # 需要注意的一點(diǎn)是Person和MyPerson類都可以調(diào)用Person數(shù)據(jù)表中的數(shù)據(jù)
    # 不同之處在于通過(guò)Person類創(chuàng)建/查找到的實(shí)例中沒(méi)有ordering屬性短条,也不能調(diào)用do_something方法
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市才菠,隨后出現(xiàn)的幾起案子茸时,更是在濱河造成了極大的恐慌,老刑警劉巖赋访,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件可都,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蚓耽,警方通過(guò)查閱死者的電腦和手機(jī)渠牲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)步悠,“玉大人签杈,你說(shuō)我怎么就攤上這事∠屯剑” “怎么了芹壕?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)接奈。 經(jīng)常有香客問(wèn)我踢涌,道長(zhǎng),這世上最難降的妖魔是什么序宦? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任睁壁,我火速辦了婚禮,結(jié)果婚禮上互捌,老公的妹妹穿的比我還像新娘潘明。我一直安慰自己,他們只是感情好秕噪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布钳降。 她就那樣靜靜地躺著,像睡著了一般腌巾。 火紅的嫁衣襯著肌膚如雪遂填。 梳的紋絲不亂的頭發(fā)上铲觉,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音吓坚,去河邊找鬼撵幽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛礁击,可吹牛的內(nèi)容都是我干的盐杂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼哆窿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼链烈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起挚躯,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤测垛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后秧均,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡号涯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年目胡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片链快。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡誉己,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出域蜗,到底是詐尸還是另有隱情巨双,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布霉祸,位于F島的核電站筑累,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏丝蹭。R本人自食惡果不足惜慢宗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奔穿。 院中可真熱鬧镜沽,春花似錦、人聲如沸贱田。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)男摧。三九已至蔬墩,卻和暖如春译打,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筹我。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工扶平, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔬蕊。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓结澄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親岸夯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子麻献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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