• Django中content-type组件的使用


    content-type组件

    ContentType是Django的内置的一个应用,可以追踪项目的所有APP和model的对应关系,并记录在ContentTpe表中,当我们的项目做数据迁移后,会有很多django自带的表,其中就有django_content_type表

    使用场景

    网上商城购物时,会有各种各样的优惠卷,比如通用优惠卷,满减卷,或者仅限特定品类的优惠卷,我们以往的方式是在数据库中,通过外键将优惠卷和不同品类的商品表关联起来

    from django.db import models
    class Electrics(models.Model):
        '''
        id  name
        1	格力空调
        2	小天鹅洗衣机
        3	好太太洗碗机
        '''
        name = models.CharField(max_length=32)
     class Foods(models.Model):
        '''
        id	name
        1	肉松小贝
        2	北京烤鸭
        3	梨膏糖
        '''
        name=models.CharField(max_length=32)
    class Clothers(model.Model):
        name=models.CharField(max_lenght=32)
    class Coupon(models.Model):
        '''
        id	name          Electrics         Foods       Clothes  ...
        1   通用优惠卷       null             null         null
        2   冰箱满减           2              null         null
        3    面包狂欢节       null             1            null
        '''
        name =models.CharField(max_length=32)
        electric_obj=models.ForeignKey(to='Electrics',null=True)
        food_obj=models.ForeignKey(to='Foods',null=True)
        cloth_obj=models.ForeignKey(to='Clothes',null=True)
    

    将所有的商品都关联到Coupon这张表中,如果是通用优惠卷,那么所有的ForeignKey对应字段的值为null,如果仅限某些商品,那么对应商品ForeignKey记录该商品的id,不相干的记录为null

    存在的问题

    1、实际中商品种类繁多,而且很可能还会持续增加,那么优惠卷标中的外键越来越多,需要频繁的修改表

    2、每条记录仅使用其中的一个或几个外键字段,这样就会造成表空间的浪费

    解决方法
    • 在model中定义ForeignKey字段,并关联到ContentType表,通常这个字段命名为content-type
    • 在model中定义PositiveIntergerField字段,用来存储关联表中的主键,通常用object_id
    • 在model中定义GenericForeignKey字段,传入上面两个字段,反向查询定义GenericRelation
    from django.db import models
    from django.contrib.contenttypes.models improt ContentType
    from django.contrib,contenttypes.models import GenericForeignKey
    
    class Electrics(models.Model):
        name=models.CharField(max_length=32)
        coupons=GenericRelation(to='Coupon')
        def __str__(self):
            return self.name
    class Foods(models.Model):
        name=models.CharField(max_length=32)
        coupons=GenericRelation(to='Coupon')
        def __str__(self):
            return self.name
    class Clothes(models.Model):
        name=models.CharField(max_length=32)
        coupons=GenericRelation(to='Coupon')
        def __str__(self):
            return self.name
    class Coupon(models.Model):
        name=models.CharField(max_length=32)
        content_type=models.ForeignKey(to=ContentType)
        object_id=models.PositiveInterField()
        content_object=GenericForeignKey('content_type','object_id')
        def __str__(self):
            return self.name
    
    from django.shortcuts import render,HttpResponse
    from app01 import models
    from django.contrib.contenttypes.models import ContentType
    
    def text(request):
        if request.method=='GET':
            content=ContentType.objects.filter(app_label='app01',model='electrics').first()
            cloth_class=content.model_class()  #相当于models.Electrics
            res=cloth_class.object.all()
            print(res)
            
            ##为三星电视(id=2)创建一条优惠记录
            s_tv=models.Electrics.objects.filter(id=2).first()
            models.Coupon.objects.create(name='电视优惠卷',content_object=s_tv)
            
            ##查询优惠卷(id=1)绑定了那些商品
            coupon_obj=models.Coupon.objects.filter(id=1).first()
            prod=coupon_obj.content_object
            print(prod)
            
            ##查询三星电视(id=2)的所有优惠卷
            res=s_tv.coupons.all()
            print(res)
            
            ##查询obj的所有优惠卷:如果没有定义反向查询字段
            content=ContentType.objects.filter(app_label='app01',model='model_name').first()
            res=models.OftenAskedQuestion.objects.filter
            (content_type=content,object_id=obj.pk).all()
            return HttpResponse('pass')
    

    总结

    当一张表和多个表FK关联,并且多个FK中只能选择其中一个或其中n个时,可以利用contenttypes app,只需要定义三个子弹就搞定,常用场景还要:一个商品的多种优惠劵、一门课程按照周期的多种价格等等

  • 相关阅读:
    ASP.NET 2.0+GridView开发中遇到ViewState MAC验证错误
    Microsoft Robotics Studio与LEGO机器人[转]
    .net反射技术的应用—如何调用Java的COM接口[转]
    ORACLE函数大全
    BCD代码
    SQL Server 2005中Datetime类型转Varchar类型
    新任项目经理的五项必修课[转载]
    利用SqlBulkCopy实现网上答题系统[转]
    电信技术名词解释:移动IP技术综述[转]
    ASP页面中访问基于.net的COM组件[转]
  • 原文地址:https://www.cnblogs.com/lzss/p/12168521.html
Copyright © 2020-2023  润新知