django conttentype freamwork

ContentType 记录了django中的模型,并且新安装的模型会自动加入。

要使用只需要在INSTALLED_APPS中增加'django.contrib.contenttypes'即可

ContentType模型

ContentType.get_object_for_this_type(**kwargs)
    通过一系列参数来获得指向model的实例.
ContentType.model_class()
    通过ContentType instance 返回 model class
>>> from django.contrib.contenttypes.models import ContentType
>>> user_type = ContentType.objects.get(app_label="auth", model="user")
>>> user_type  
>>> user_type.model_class() 
<class 'class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido') 
<User: Guido>
class ContentTypeManager
    clear_cache()
        django 自己会处理好
    get_for_model(model)
        参数为一个其他model的 class 类或者实例,返回content type的实例
    get_by_natural_key(app_label,model)
        返回content type的实例

Generic relations

在你的model中增加一个外键到ContentType能让你的模型更高效的绑定到其他model class. 一个 tagging system的例子:

from django.db import models
from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 
class TaggedItem(models.Model):
     tag = models.SlugField()
     content_type = models.ForeignKey(ContentType)
     object_id = models.PositiveIntegerField()
     content_object = generic.GenericForeignKey('content_type', 'object_id')
     def __unicode__(self):
         return self.tag 
         
一个普通的ForeignKey 只能指定具体的一个model,而contenttypes 能提供特殊的field 解决这个问题,指向任意的model

GenericForeignKey
有三个部分来构建一个GenericForeignKey:
    1.在model中增加一个field为ContentType的ForeignKey.
    2.给你的model中加一个field来存储指向model的主键.这个field一般命名为object_id.它是主键
    3.增加一个GenericForeignKey类型的field, 传递前面两个field的值. 默认为"content_type" 和"object_id",
 

object_id 的类型不一定要和相关连的model的primary key fields一样,只要能强制转换过来就可以。为了最大的兼容性可以使用TextField,但是会降低数据库效率

这就像一个普通的ForeignKey; 每一个TaggedItem的content_object返回它实际指向的model,你能在创建TaggedItem的时候给它赋值.

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

GenericForeignKey不能使用 (filter()和exclude()等数据库的API) :

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

Reverse generic relations

class GenericRelation
如果你知道哪个model用的很多, 可以增加一个 "reverse" generic relationship来增加API.
class Bookmark(models.Model):
     url = models.URLField()
     tags = generic.GenericRelation(TaggedItem) 

Bookmark instances 将有一个tags属性, 并且和TaggedItems 联系起来:

>>> b = Bookmark(url='http://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() 
[<TaggedItem: django>, <TaggedItem: python>] 

GenericRelation接收 content-type 和 object-id 作为参数,

如果 model 的GenericForeignkey 用的不是默认field names ,在建立GeneriRelation的时候必须传递field的name给它

例如, 如果TaggedItem model 使用 fields content_type_fk and object_primary_key 生成 generic foreign key,代码如下

>>> b = Bookmark.objects.get(url='http://www.djangoproject.com/') 
>>> bookmark_type = ContentType.objects.get_for_model(b) 
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,object_id=b.id) 
[<TaggedItem: django>,] 

当然, 如果你不使用reverse relationship, 也可以这么写:

>>> b = Bookmark.objects.get(url='http://www.djangoproject.com/') 
>>> bookmark_type = ContentType.objects.get_for_model(b) 
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, ... object_id=b.id) 
[<TaggedItem: django>, <TaggedItem: python>] 
不像ForeignKey,GenericForeignKey不接收on_delete参数; 如果需要的话,可以使用pre_deletesignal.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值