关于 contenttypes 的使用

一、django中自带的app的介绍

  • 1、INSTALLED_APPS中已注册的app

    INSTALLED_APPS = [
        'django.contrib.admin', # 后台管理系统
        'django.contrib.auth', # 权限
        'django.contrib.contenttypes', # 本章节介绍的
        'django.contrib.sessions', # session模块
        'django.contrib.messages',
        'django.contrib.staticfiles' # 处理静态文件的
    ]
    
  • 2、关于contenttypes生成的表(其实就是一张存储app名称及app下面的拥有表名的总表)

    mysql> desc django_content_type;
    +-----------+--------------+------+-----+---------+----------------+
    | Field     | Type         | Null | Key | Default | Extra          |
    +-----------+--------------+------+-----+---------+----------------+
    | id        | int(11)      | NO   | PRI | NULL    | auto_increment |
    | app_label | varchar(100) | NO   | MUL | NULL    |                |
    | model     | varchar(100) | NO   |     | NULL    |                |
    +-----------+--------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
    
    mysql>
    
  • 3、最原始的数据(如果自己注册的App中有model就会在这个表中插入数据)

    mysql> select * from django_content_type;
    +----+--------------+-------------+
    | id | app_label    | model       |
    +----+--------------+-------------+
    |  1 | admin        | logentry    |
    |  3 | auth         | group       |
    |  2 | auth         | permission  |
    |  4 | auth         | user        |
    |  5 | contenttypes | contenttype |
    |  6 | sessions     | session     |
    +----+--------------+-------------+
    6 rows in set (0.00 sec)
    
    mysql>
    

二、关于django_content_type使用场景

一张表需要与多张表创建外键关联的时候

  • 1、使用场景举例

    • 1.课程一对应的价格及上课周期
    • 2.课程二对应的价格及上课周期
    • 3.上面原本可以创建4张表,课程与价格是外键关联起来(两张价格表有点多余)
    • 4.现在做的两个课程表对应一张价格表
  • 2、使用django_content_type创建上面需求的图表分析

    django_content_type的使用

三、django代码实现

  • 1、创建model

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    
    class CourseModel1(models.Model):
        """
        课程表一
        """
        name = models.CharField(max_length=30, null=False, blank=False, verbose_name='课程名称')
    
        class Meta(object):
            verbose_name = '课表表一'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    class CourseModel2(models.Model):
        """
        课程表二
        """
        name = models.CharField(max_length=20, null=False, blank=False, verbose_name='课程名称')
    
        class Meta(object):
            verbose_name = '课程二'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    class PriceModel(models.Model):
        """
        课程价格表
        """
        time_choices = (
            ('7d', '7天'),
            ('90d', '90天'),
            ('180d', '180天')
        )
        time = models.CharField(max_length=20, choices=time_choices, default='7d', verbose_name='学习周期')
        price = models.FloatField(default=0, verbose_name='课程价格')
        # PositiveIntegerField表示正整数的意思
        object_id = models.PositiveIntegerField(verbose_name='课程表id')
        content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, verbose_name='课程')
    
  • 2、生成表

    python manage.py makemigration
    python manage.py migrate
    
  • 3、创建数据(课程表就不演示)

    from django.shortcuts import HttpResponse
    from .models import PriceModel
    from django.contrib.contenttypes.models import ContentType
    
    def test(request):
        # 创建价格表数据
        PriceModel.objects.create(
            time='7d',
            price=200,
            object_id=1,
            # 创建外键
            content_type=ContentType.objects.get(model='coursemodel1')
        )
        return HttpResponse('hello')
    
  • 4、查询数据

    def test(request):
        price = PriceModel.objects.get(id=2)
        print(price.content_type)
        return HttpResponse('hello')
    

四、补充说明一(GenericForeignKey的使用)

  • 1、使用GenericForeignKey方便添加数据与查询数据

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    
    class PriceModel(models.Model):
        """
        课程价格表
        """
        time_choices = (
            ('7d', '7天'),
            ('90d', '90天'),
            ('180d', '180天')
        )
        time = models.CharField(max_length=20, choices=time_choices, default='7d', verbose_name='学习周期')
        price = models.FloatField(default=0, verbose_name='课程价格')
        # PositiveIntegerField表示正整数的意思
        object_id = models.PositiveIntegerField(verbose_name='课程表id')
        content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, verbose_name='课程')
        # 不会在数据库中生成列,只是帮助你进行添加与查询的使用
        content_object = GenericForeignKey('content_type', 'object_id')
    
  • 2、添加数据

    from .models import PriceModel, CourseModel2
    
    def test(request):
        PriceModel.objects.create(
            time='90d',
            price=1000,
            object_id=3,
            # 直接使用表对象插入
            content_object=CourseModel2.objects.get(id=3)
        )
        return HttpResponse('hello')
    
  • 3、查询数据

    def test(request):
        price = PriceModel.objects.get(id=3)
        print(price.content_object.name)
        return HttpResponse('hello')
    

五、补充说明二(GenericRelation反向查找[根据课程查找价格列表])

  • 1、修改课程表的model

    class CourseModel2(models.Model):
        """
        课程表二
        """
        name = models.CharField(max_length=20, null=False, blank=False, verbose_name='课程名称')
        price_list = GenericRelation('PriceModel', verbose_name='价格列表')
    
        class Meta(object):
            verbose_name = '课程二'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
  • 2、通过课程表的id查找到相对应的金额

    def test(request):
        obj = CourseModel2.objects.get(id=2)
        for item in obj.price_list.all():
            print(item.time, item.content_object.name, item.price)
        return HttpResponse('hello')
    

results matching ""

    No results matching ""