溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在Django中使用contenttypes 框架

發(fā)布時(shí)間:2021-04-13 17:36:20 來(lái)源:億速云 閱讀:242 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

本篇文章為大家展示了怎么在Django中使用contenttypes 框架,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

一、什么是Django ContentTypes?

Django ContentTypes是由Django框架提供的一個(gè)核心功能,它對(duì)當(dāng)前項(xiàng)目中所有基于Django驅(qū)動(dòng)的model提供了更高層次的抽象接口。 

二、Django ContentTypes做了什么?

當(dāng)使用django-admin初始化一個(gè)django項(xiàng)目的時(shí)候,可以看到在默認(rèn)的INSTALL_APPS已經(jīng)包含了django.contrib.contenttypes:

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

而且注意django.contrib.contenttypes是在django.contrib.auth之后,這是因?yàn)閍uth中的permission系統(tǒng)是根據(jù)contenttypes來(lái)實(shí)現(xiàn)的。

我們來(lái)查詢查閱了一下django.contrib.contenttypes.models文件:

class ContentType(models.Model):
  app_label = models.CharField(max_length=100)
  model = models.CharField(_('python model class name'), max_length=100)
  objects = ContentTypeManager()

  class Meta:
    verbose_name = _('content type')
    verbose_name_plural = _('content types')
    db_table = 'django_content_type'
    unique_together = (('app_label', 'model'),)

  def __str__(self):
    return self.name

大家可以看到ContentType就是一個(gè)簡(jiǎn)單的django model,而且它在數(shù)據(jù)庫(kù)中的表的名字為django_content_type。

這個(gè)表的名字一般都不會(huì)陌生,在第一次對(duì)Django的model進(jìn)行migrate之后,就可以發(fā)現(xiàn)在數(shù)據(jù)庫(kù)中出現(xiàn)了一張默認(rèn)生成的名為django_content_type的表。

如果沒(méi)有建立任何的model,默認(rèn)django_content_type是這樣的:

怎么在Django中使用contenttypes 框架

因此,django_content_type記錄了當(dāng)前的Django項(xiàng)目中所有model所屬的app(即app_label屬性)以及model的名字(即model屬性)。

當(dāng)然,django_content_type并不只是記錄屬性這么簡(jiǎn)單,contenttypes是對(duì)model的一次封裝,

因此可以通過(guò)contenttypes動(dòng)態(tài)的訪問(wèn)model類型,而不需要每次import具體的model類型。

  • ContentType實(shí)例提供的接口 

    • 通過(guò)model或者model的實(shí)例來(lái)尋找ContentType類型

    • 通過(guò)id尋找ContentType類型,這個(gè)跟傳統(tǒng)的get方法的區(qū)別就是它跟get_for_model共享一個(gè)緩存,因此更為推薦。

    • 使用當(dāng)前ContentType類型所代表的模型類做一次get查詢

    • 獲取當(dāng)前ContentType類型所代表的模型類

    • ContentType.model_class() 

    • ContentType.get_object_for_this_type() 

    • ContentType管理器(manager)提供的接口 

    • ContentType.objects.get_for_id() 

    • ContentType.objects.get_for_model() 

三、Django ContentTypes的使用場(chǎng)景

在我們這個(gè)項(xiàng)目中各種商品的優(yōu)惠卷就運(yùn)用到了這個(gè)知識(shí)點(diǎn):

假使我們models下有這幾張表:

class Electrics(models.Model): #電器類
  name = models.CharField(max_length=32)
  price= models.IntegerField(default=100)

  def __str__(self):
    return self.name


class Foods(models.Model):   #食物類
  name = models.CharField(max_length=32)
  price = models.IntegerField(default=100)

  def __str__(self):
    return self.name


class Clothes(models.Model):  #衣服類
  name = models.CharField(max_length=32)
  price= models.IntegerField(default=100)
  def __str__(self):
    return self.name

class Coupon(models.Model):  #優(yōu)惠券
  name = models.CharField(max_length=32)

  def __str__(self):
    return self.name

我們先來(lái)考慮一個(gè)問(wèn)題,如何把這些商品和優(yōu)惠卷相關(guān)聯(lián)?

一種商品一個(gè)優(yōu)惠卷,那我們就在表中加入一種商品的優(yōu)惠券,就是一個(gè)一對(duì)多的ForeignKey,那么多個(gè)商品就有各種優(yōu)惠卷,

但是一種商品的特定優(yōu)惠卷在表結(jié)構(gòu)中,就那個(gè)字段有值,別的不相關(guān)的記錄為null,而且每增加一個(gè)商品,又要手動(dòng)的去添加外鍵,

這是繁瑣的!

所以我們就使用contenttypes 應(yīng)用中提供的特殊字段GenericForeignKey,我們可以解決上面的問(wèn)題:

只需要以下三步:

  • 在model中定義ForeignKey字段,并關(guān)聯(lián)到ContentType表。通常這個(gè)字段命名為“content_type”

  • 在model中定義PositiveIntegerField字段,用來(lái)存儲(chǔ)關(guān)聯(lián)表中的主鍵。通常這個(gè)字段命名為“object_id”

  • 在model中定義GenericForeignKey字段,傳入上述兩個(gè)字段的名字。

具體實(shí)例代碼:

class Coupon(models.Model):
  name = models.CharField(max_length=32)

  content_type = models.ForeignKey(to=ContentType) # step 1
  object_id = models.PositiveIntegerField() # step 2
  content_object = GenericForeignKey('content_type', 'object_id') # step 3

  def __str__(self):
    return self.name

這樣的話不管表的數(shù)據(jù)都可以查詢出來(lái),而且添加新的商品的商品,也不需要?jiǎng)觾?yōu)惠券的源碼。

但我們?cè)诓樵兊倪^(guò)程中,用ORM實(shí)在太繁瑣了,所以還有一個(gè)反向查詢的方法:

就是在每個(gè)商品中關(guān)聯(lián) 綁定一個(gè)關(guān)系:

coupons = GenericRelation(to='Coupon') # 用于反向查詢,不會(huì)生成表字段

上述內(nèi)容就是怎么在Django中使用contenttypes 框架,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI