Django content-type组件
介绍Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口。 Contenttypes应用的核心是ContentType模型,位于django.contrib.contenttypes.models.ContentType。 ContentType的实例表示并保存项目中安装的模型的信息,每当有新的模型时会自动创建新的ContentType实例。 只要使用django-admin startproject 命令创建的Django项目(PyCharm创建Django项目同理),默认都会在settings.py的INSTALLED_APPS列表中安装好django.contrib.contenttypes。 我们执行了数据迁移命令之后,会自动在数据库中创建一个名为django_content_type的表。 表结构如下图所示: 其中,app_label字段存储了APP的名称,model字段存储了APP下的具体的模型类的名称。 应用场景我们在网上po一段散文诗也可以po一张旅途的风景图,文字可以被评论,图片也可以被评论。我们需要在数据库中建表存储这些数据,我们可能会设计出下面这样的表结构。 class Post(models.Model): """帖子表""" author = models.ForeignKey(User) title = models.CharField(max_length=72) class Picture(models.Model): """图片表""" author = models.ForeignKey(User) image = models.ImageField() class Comment(models.Model): """评论表""" author = models.ForeignKey(User) content = models.TextField() post = models.ForeignKey(Post,null=True,blank=True,on_delete=models.CASCADE) picture = models.ForeignKey(Picture,on_delete=models.CASCADE) 这表结构看起来不太简洁,我们画个图来看一下: 能用是能用,但是评论表有点冗余啊。好多列都空着呢啊! 我们优化一下,我们在评论表里不直接外键关联 文字和图片,而是存储一下关联的表名和字段,这样就好很多了。 看下图: 那我们不妨步子再大一点,再往前走一步试试,因为表名在评论里面重复了很多次,我们完全可以把Django项目中的表名都存储在一个表里面。然后评论表里外键关联这个表就可以了。 这个时候我们就用上了前面讲到的contenttypes,借助contenttypes我们就能够在创建Comment的时候再决定和Post关联还是和Picture关联。 在models.py中使用django.contrib.contenttypes中提供的特殊字段GenericForeignKey来实现: class Comment(models.Model): """评论表""" author = models.ForeignKey(User) content = models.TextField() content_type = models.ForeignKey(ContentType) # 外键关联django_content_type表 object_id = models.PositiveIntegerField() # 关联数据的主键 content_object = GenericForeignKey('content_type','object_id') contenttypes使用import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE","about_contenttype.settings") import django django.setup() from app01.models import Post,Picture,Comment from django.contrib.auth.models import User # 准备测试数据 user_1 = User.objects.create_user(username='aaa',password='123') user_2 = User.objects.create_user(username='bbb',password='123') user_3 = User.objects.create_user(username='ccc',password='123') post_1 = Post.objects.create(author=user_1,title='Python入门教程') post_2 = Post.objects.create(author=user_2,title='Python进阶教程') post_3 = Post.objects.create(author=user_1,title='Python入土教程') picture_1 = Picture.objects.create(author=user_1,image='小姐姐01.jpg') picture_2 = Picture.objects.create(author=user_1,image='小姐姐02.jpg') picture_3 = Picture.objects.create(author=user_3,image='小哥哥01.jpg') # 给帖子创建评论数据 comment_1 = Comment.objects.create(author=user_1,content='好文!',content_object=post_1) # 给图片创建评论数据 comment_2 = Comment.objects.create(author=user_2,content='好美!',content_object=picture_1) 接下来如果我们想要查看某篇帖子或者某个照片的所有评论,这个时候就可以用上另外一个工具--GenericRelation了。 from django.contrib.contenttypes.fields import GenericRelation 修改models.py中的Post和Picture,添加用于反向查询的comments字段: class Post(models.Model): """帖子表""" author = models.ForeignKey(User) title = models.CharField(max_length=72) comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段) class Picture(models.Model): """图片表""" author = models.ForeignKey(User) image = models.ImageField() comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段) 查询示例: post_1 = Post.objects.filter(id=1).first() comment_list = post_1.comments.all() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |