1、什麼是Django ContentTypes?html
一、Django 包含一個ContentTypes 應用,它能夠追蹤安裝在你的Django 項目裏的全部應用,並提供一個高層次的、通用的接口用於與你的模型進行交互。python
二、Django ContentTypes是由Django框架提供的一個核心功能,它對當前項目中全部基於Django驅動的model提供了更高層次的抽象接口。sql
三、Contenttypes 的核心應用是ContentType模型,存在於 django.contrib.contenttypes.models.ContentType。ContentType 的實例表示並存儲你的項目當中安裝的應用的信息,而且每當新的模型安裝時會自動建立新的 ContentType 實例。數據庫
四、ContentType 實例具備返回它們表示的模型類的方法,以及從這些模型查詢對象的方法。ContentType 還有一個自定義的管理器用於添加方法來與ContentType工做,以及用於得到ContentType實例的特定模型。django
五、你的模型和ContentType 之間的關係還能夠用於一個模型實例和任意一個已經安裝的模型的實例創建「generic關聯」。緩存
2、Django ContentTypes作了什麼?session
一、當使用django-admin初始化一個django項目的時候,能夠看到在默認的INSTALL_APPS已經包含了django.contrib.contenttypes:app
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以後,這是由於auth中的permission系統是根據contenttypes來實現的。
二、Contenttypes 框架包含在django-admin startproject 建立的默認的INSTALLED_APPS列表中
三、Admin 應用使用它來記錄經過Admin 界面添加或更改每一個對象的歷史。
四、Django 的authentication 框架用它來授用戶權限給特殊的模型。
二、關於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就是一個簡單的django model,並且它在數據庫中的表的名字爲django_content_type。
三、
有經驗的Django開發者對於這個表的名字通常都不會陌生,在第一次對Django的model進行migrate以後,就能夠發如今數據庫中出現了一張默認生成的名爲django_content_type的表。ide
若是沒有創建任何的model,默認django_content_type是這樣的:
sqlite> select * from django_content_type; 1|admin|logentry 2|auth|group 3|auth|user 4|auth|permission 5|contenttypes|contenttype 6|sessions|session
註釋:一、django_content_type記錄了當前的Django項目中全部model所屬的app(即app_label屬性)以及model的名字(即model屬性)。
二、每個ContentType 實例有兩個字段,共同來惟一描述一個已經安裝的模型。
app_label:模型所在的應用的名稱。 這取自模型的app_label 屬性,並只包括應用的Python 導入路徑的最後的部分。例如,"django.contrib.contenttypes"的app_label 是"contenttypes"。
model:模型的類的名稱。
四、
django_content_type並不僅是記錄屬性這麼簡單,contenttypes實際上是對model的一次封裝,所以能夠經過contenttypes動態的訪問model類型,而不須要每次import具體的model類型。
一、ContentType實例提供的接口 ContentType.model_class() # 獲取當前ContentType類型所表明的模型類 ContentType.get_object_for_this_type() #使用當前ContentType類型所表明的模型類作一次get查詢
二、ContentType管理器(manager)提供的接口 ContentType.objects.get_for_id() #經過id尋找ContentType類型,這個跟傳統的get方法的區別就是它跟get_for_model共享一個緩存,所以更爲推薦。 ContentType.objects.get_for_model() #接收一個模型類或模型的實例,並返回表示該模型的ContentType實例
ContentType.objects.get_for_models()
3、Django ContentTypes的使用方法
一、每個 ContentType 都有一些方法容許你用ContentType實例來到達它所表明的model, 或者從model取出對象:
示例:
例如,咱們能夠查找User 模型的ContentType︰
>>> from django.contrib.contenttypes.models import ContentType
>>> user_type = ContentType.objects.get(app_label="auth", model="user")
>>> user_type
<ContentType: user>
而後使用它來查詢一個特定的User,或者訪問 User 模型類︰
>>> user_type.model_class()
<class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido')
<User: Guido>
二、ContentTypeManager(自定義的管理器ContentTypeManager)
clear_cache() #清除ContentType 用於跟蹤模型的內部緩存,它已爲其建立ContentType 實例。你可能不須要本身調用此方法;Django 將在它須要的時候自動調用。
get_for_id(id) #經過ID查找ContentType。因爲此方法使用與get_for_model() 相同的共享緩存,建議使用這個方法而不是一般的 ContentType.objects.get(pk=id)
get_for_model(model[, for_concrete_model=True])#接收一個模型類或模型的實例,並返回表示該模型的ContentType 實例。for_concrete_model=False 容許獲取代理模型的ContentType
get_for_models(*models[, for_concrete_models=True])#接收可變數目的模型類,並返回一個字典,將模型類映射到表示它們的ContentType 實例。for_concrete_model=False 容許獲取代理模型的ContentType。
四
、ContentType的通用類型
假設如下的應用場景:
class Coupon(models.Model):
"""優惠券生成規則
ID 優惠券名稱 A FK B.FK c.FK
1 通用 null null
2 滿100-10 8 1
3 滿200-30 8 2
4 滿200-30 9 1
ID 優惠券名稱 content_type_id(表) object_id(表中數據ID)
1 通用 null null
2 滿100-10 8 1
3 滿200-30 8 2
4 滿200-30 9 1
總結:
"""
name = models.CharField(max_length=64, verbose_name="活動名稱")
brief = models.TextField(blank=True, null=True, verbose_name="優惠券介紹")
# 那個表?
content_type = models.ForeignKey(ContentType, blank=True, null=True)
# 對象ID
object_id = models.PositiveIntegerField("綁定課程", blank=True, null=True, help_text="能夠把優惠券跟課程綁定")
content_object = GenericForeignKey('content_type', 'object_id')
#註釋:ContentType提供了一種GenericForeignKey的類型,經過這種類型能夠實如今Comment對其他全部model的外鍵關係。 一張表和其餘多個表管理,並建立多個FK時,而且多個Fk只能選擇其中一個時,能夠用ContentType。 經過使用一個content_type屬性代替了實際的model,而object_id則表明了實際model中的一個實例的主鍵,其中,content_type和object_id的字段命名都是做爲字符串參數傳進content_object的。
content_object = fields.GenericForeignKey() #應該能夠這麼寫