Django contenttypes 组件

Django contenttypes 组件

Django包含一个contenttypes应用程序,可以跟踪Django驱动的项目中安装的所有模型,为您的模型提供高级通用界面。

Contenttypes应用的核心是ContentType模型,位于django.contrib.contenttypes.models.ContentType。 ContentType的实例表示并保存项目中安装的模型的信息,每当有新的模型时会自动创建新的ContentType实例。

ContentType具有返回它们所代表的模型类以及从这些模型查询对象的方法的实例。ContentType 还有一个自定义管理器,它添加了使用ContentType和获取ContentType 特定模型实例的方法。

模型之间的关系 ContentType也可用于启用某个模型的实例与已安装的任何模型的实例之间的“通用”关系。

安装 contenttypes

在Django项目中,默认安装 contenttypes app

ContentType model

ContentType部分源码

@python_2_unicode_compatible
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'),)

动态关联

实现动态关联,一个外键字段动态关联不同 model 。 GenericForeignKey

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class TaggedItem(models.Model):
    tag = models.SlugField()
    # 1. 外键关联 ContentType这张表(自带的) --> 确定了关联哪张表
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)4
    # 2. 只要是一个能保存数据库id的字段就可以  --> 确定数据
    object_id = models.PositiveIntegerField()
    # 3. 告诉Django由上面两条字段唯一确定关联的一条记录
    content_object = GenericForeignKey('content_type', 'object_id') 

    def __str__(self):              # __unicode__ on Python 2
        return self.tag

创建数据

>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()
# 同 t = TaggedItem.object.create(content_object=guido, tag='bdfl')
>>> t.content_object
<User: Guido>

由于方式GenericForeignKey 实现,你不能直接使用的过滤器等领域(filter() 以及exclude()通过数据库API,例如)。由于 GenericForeignKey不正常的领域对象,这些例子工作:

# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)

反向查询

如果您知道最常使用的模型,还可以添加“反向”通用关系以启用其他API。例如:

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation

class Bookmark(models.Model):
    url = models.URLField()
    tags = GenericRelation(TaggedItem)
	# tags = GenericRelation(to='TaggedItem')

Bookmark每个实例都有一个tags属性,可以用来检索它们的关联TaggedItems

>>> b = Bookmark(url='https://www.djangoproject.com/')
>>> b.save()
>>> t1 = TaggedItem(content_object=b, tag='django')
>>> t1.save()
>>> t2 = TaggedItem(content_object=b, tag='python')
>>> t2.save()
>>> b.tags.all()
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
posted @ 2019-08-03 17:42  写bug的日子  阅读(122)  评论(0编辑  收藏  举报