zoukankan      html  css  js  c++  java
  • Django contenttypes 组件

    contenttypes组件

    介绍

    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, null=True, blank=True, 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()
  • 相关阅读:
    SPOJ 694 (后缀数组) Distinct Substrings
    POJ 2774 (后缀数组 最长公共字串) Long Long Message
    POJ 3693 (后缀数组) Maximum repetition substring
    POJ 3261 (后缀数组 二分) Milk Patterns
    UVa 1149 (贪心) Bin Packing
    UVa 12206 (字符串哈希) Stammering Aliens
    UVa 11210 (DFS) Chinese Mahjong
    UVa (BFS) The Monocycle
    UVa 11624 (BFS) Fire!
    HDU 3032 (Nim博弈变形) Nim or not Nim?
  • 原文地址:https://www.cnblogs.com/liwenzhou/p/10277883.html
Copyright © 2011-2022 走看看