• 使用ContentType处理大量的外键关系


    问题分析

    在之前的一个商城的项目中使用了mysql, 提到mysql就是外键, 多对多等等一系列的表关系

    因为是一个商城的项目, 这里面有优惠券, 商品有很多的分类, 不同的商品又有不同的优惠券

    其实要说的也就是商品和优惠券的关系, 

    说到关系那肯定就是用外键, 优惠券外键商品, 但是有一个问题, 一个外键只能指向一张表

    现在假如有10个商品表, 一张优惠券表, 要想在一张表中给另外10张表创建外键关系, 那就需要10个外键关系, 10个外键字段

    可想而知, 这种方法是不可行的

    其实有一种办法那就是, 在优惠券表不直接关联商品表, 而是搞一个中间表, 关联这个中间表, 那这个中间表应该张什么样子呢?

    这张表中存储是的app名字和表的名字

    id            app_name        model_name
    1              mian            Human_insurance
    2              main            Life_insurance

    然后优惠券表就这张表建立外键关系, 然后在优惠券中在存储一个object_id, 通过外键找到关联的表, 通过object_id找到表中的对象, 这样就OK了

    上面的正常人的想法, django的开发者也是正常人, 哈哈, 他们也想到了, 所以django提供了这样的一张表.

    使用ContentType处理外键关系

    下面是我写的一个小demo, 这里面就利用了django提供的ContentType来处理外键关系

    模型表

    from django.db import models
    from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
    from django.contrib.contenttypes.models import ContentType
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.FloatField()
        category_choices = (("chinese", "中文"), ("english", "英文"), ("development", "开发"), ("network", "网络"))
        category = models.CharField(choices=category_choices, max_length=32)
        pub_date = models.DateTimeField(null=True, blank=True)
    
        content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE)
        # 定位对象的id
        object_id = models.PositiveIntegerField(blank=True, null=True)
        # 定位对象
        content_object = GenericForeignKey('content_type', 'object_id')
    
    
        def __str__(self):
            return self.title
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        address = models.CharField(max_length=128)
        books = GenericRelation("Book")
    
        def __str__(self):
            return self.name

    book表中的字段介绍

    content_type: 是一个外键字段, 关联的表就是和上面自己构造的表结构一致, 只不过是Django提供的

     

    这样就方便了很多.

    object_id: 这个字段存储的就是某张表中的某个对象的id, 所以就是用数字类型进行存储

    content_object: 这个字段是一个GenericForeignKey, 这个字段给我们提供了很大的方便, 但是这个字段不会真实的在数据库中创建,

    为什么说提供了很大的方便呢?

    因为, 在创建book对象的时候可以给content_object传一个对象, 这个字段能够自动找到这个对象的app_name和model_name, 并且填充到content_type和object_id中

    这样就不用我们自己去查了

    下面就使用这个字段对数据库进行操作

    查看书籍的出版社

    a = models.Book.objects.filter(id=5).first()
    print(a.content_object)
    #content_object通过content_type和object_id定位到对象

    创建book

    创建book的时候需要关联出版社, 这就用道了contentType, 只传一个content_object参数就可以了

    # 先查询出出版社
    b = models.Publish.objects.filter(id=3).first()
    # 创建book
    c = models.Book.objects.create(title="test", price=99.9, category="english", content_object=b)
    print(c)

    修改book的出版社

    e = models.Book.objects.filter(title="test").first()
    e.content_object = models.Publish.objects.filter(id=4).first()
    e.save()

    删除

    因为我使用的的django2.0, 在创建外键的时候必须指定参数on_delete=models.CASCADE, 将出版社删除了book也就没了

    models.Publish.objects.filter(id=1).delete()

    总结

    使用ContentType来处理大量的外键关系

  • 相关阅读:
    Centos下一个server安装的版本号mysql
    android 玩愤怒的小鸟等游戏的时候全屏TP失败
    6.8 一般处理语言
    [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem
    POJ1185:火炮(减少国家)
    教你如何下载音乐的网站只试镜
    实现js呼叫流行
    [Angular 2] Async Http
    [Typescript] Function defination
    [React] React Router: setRouteWillLeaveHook
  • 原文地址:https://www.cnblogs.com/594504110python/p/10371482.html
Copyright © 2020-2023  润新知