zoukankan      html  css  js  c++  java
  • django框架基础ORM进阶长期维护

    ###############    ORM进阶---contenttype    ################

    设计思路:

    """
    路飞有两种课,专题课和学位课,
    专题课都是简单的内容,基础的课程模块,
    学位课都是大课程,全套课程, 
    怎么设计价格策略的问题?
    第一种设计:
    价格策略表:
    id,价格, 期限,专题课id,学位课id
    1    11    3个月  1       空
    1    11    6个月  1       空
    1    11    9个月  1       空
    1    11    9个月  2       空
    1    11    3个月  空      1
    1    11    6个月  空      1
    1    11    9个月  空      1
    1    11    9个月  空      2
    这种设计就是每一个课程有多个价格策略,但是会有重复,每个价格策略有的只适用专题课,有的是只适用学位课, 
    第二种设计:
    价格策略表:
    id,价格, 期限,表中数据id ,表id(使用 django_content_type)
    1    11    3个月  1            1
    1    11    6个月  2            2
    1    11    9个月  1            1
    对应的表
    1 course
    2 degree
    这种设计思路非常不错,这是django支持的方式,django里面有一张表 django_content_type
    
    
    """

     表结构

    #
    #
    # from django.contrib.contenttypes.models import ContentType
    # from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    #
    #
    # class DegreeCourse(models.Model):
    #     """学位课程"""
    #     name = models.CharField(max_length=128, unique=True)
    #     course_img = models.CharField(max_length=255, verbose_name="缩略图")
    #     brief = models.TextField(verbose_name="学位课程简介", )
    #
    #
    # class SubjectCourse(models.Model):
    #     """专题课程"""
    #     name = models.CharField(max_length=128, unique=True)
    #     course_img = models.CharField(max_length=255)
    #
    #     # 不会在数据库生成列,只用于帮助你进行查询
    #     policy_list = GenericRelation("PricePolicy")  # 不会在数据库生成列,只用于帮助你进行查询
    #
    #
    # class PricePolicy(models.Model):
    #     """价格与有课程效期表"""
    #     content_type = models.ForeignKey(ContentType)  # 关联course or degree_course
    #     object_id = models.PositiveIntegerField()  # 正整数,
    #
    #     #不会在数据库生成列,只用于帮助你进行添加和查询
    #     content_object = GenericForeignKey('content_type', 'object_id')  # 把两个字段放到一个对象里面去了
    #
    #
    #     valid_period_choices = (
    #         (1, '1天'),
    #         (3, '3天'),
    #         (7, '1周'), (14, '2周'),
    #         (30, '1个月'),
    #         (60, '2个月'),
    #         (90, '3个月'),
    #         (180, '6个月'), (210, '12个月'),
    #         (540, '18个月'), (720, '24个月'),
    #     )
    #     valid_period = models.SmallIntegerField(choices=valid_period_choices)
    #     price = models.FloatField()

    操作:

    from django.shortcuts import render,HttpResponse
    from django.contrib.contenttypes.models import ContentType
    # 在使用contenttype的时候如何操作orm,
    def test(request):
        # 1.在价格策略表中添加一条数据
        models.PricePolicy.objects.create(
            valid_period=7,
            price=6.6,
            content_type=ContentType.objects.get(model='SubjectCourse'),
            object_id=1
        )
        # 这是第二种方式,
        models.PricePolicy.objects.create(
            valid_period=14,
            price=9.9,
            content_object=models.Course.objects.get(id=1)
            # 对应的model表中需要添加这个
            # content_object = GenericForeignKey('content_type', 'object_id')  # 把两个字段放到一个对象里面去了
        )
    
        # 2. 根据某个价格策略对象,找到他对应的表和数据,如:管理课程名称
        price = models.PricePolicy.objects.get(id=2)
        print(price.content_object.name)  # 自动帮你找到
    
        # 3.找到某个课程关联的所有价格策略
        obj = models.Course.objects.get(id=1)
        for item in obj.policy_list.all():
            print(item.id,item.valid_period,item.price)
            # 需要在专题表中添加这个GenericRelation
            # policy_list = GenericRelation("PricePolicy")  # 不会在数据库生成列,只用于帮助你进行查询
    
        return HttpResponse('...')
    
    """
    总结:
    1,使用到了django的表ContentType
    2,GenericRelation
    3,GenericForeignKey
    在价格策略和优惠券的地方都会使用这种结构,评论也是,视频可以评论文章可以评论,
    这种设计非常有利于拓展,
    """

      

     ###############    django--事务,原子操作    ###############

    if __name__ == "__main__":
        import os,django
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_django.settings")
        django.setup()
        from app01 import models
        import datetime
    
        # 事务,原子操作,
        try:
            from django.db import transaction #导入一个transaction
            with transaction.atomic():  #atomic原子,下面的语句要么都成功,要么都不成功,这样就可以了,这就是事务,
                new_publisher = models.Publisher.objects.create(name="火星出版社")
                models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
        except Exception as e:
            print(str(e))

    ###############  Django终端打印SQL语句    ################

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }

    ###############    在Python脚本中调用Django环境    ################

    import os
    
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
        import django
        django.setup()
    
        from app01 import models
    
        books = models.Book.objects.all()
        print(books)

    ###############    执行原生sql   ################

    if __name__ == "__main__":
        import os, django
    
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        django.setup()
        from app01 import models
    
        # 在模型查询API不够用的情况下,我们还可以使用原始的SQL语句进行查询。
        # Django 提供两种方法使用原始SQL进行查询:
        # 一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。
    
    
        # 执行原生查询
        for p in models.Publish.objects.raw('SELECT * FROM app01_publish'):
            print(p)
        # raw()查询可以查询其他表的数据。
        for p in models.Publish.objects.raw('SELECT nid,name FROM app01_author'):
            print(p.nid,p.name)
    
        # raw()方法自动将查询字段映射到模型字段。
        # 还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典
        d = {'name': 'sname'}
        for p in models.Publish.objects.raw('SELECT * FROM app01_author', translations=d):
            print(p.nid,p.sname)
    
        # 原生SQL还可以使用参数,注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!
        d = {'name': 'sname'}
        ret = models.Publish.objects.raw('select * from app01_publish where nid > %s', translations=d, params=[1, ])
        for p in ret:
            print(p.nid,p.sname)
    
        # 直接执行自定义SQL
        # 有时候raw()方法并不十分好用,很多情况下我们不需要将查询结果映射成模型
        # 我们可以直接从django提供的接口中获取数据库连接,然后像使用pymysql模块一样操作数据库。
        from django.db import connection, connections
        cursor = connection.cursor()  # cursor = connections['default'].cursor()
        cursor.execute("""SELECT * from app01_publish where nid = %s""", [1])
        ret = cursor.fetchone()
    
        print(ret)

    ###############    ORM进阶    ################

    django中怎么写原生SQL
    
    列举django orm中三种能写sql语句的方法
    
    1,使用extra:查询人民邮电出版社出版并且价格大于50元的书籍
    Book.objects.filter(publisher__name='人民邮电出版社').extra(where=['price>50']) 
    
    2,使用raw
    books=Book.objects.raw('select * from hello_book')  
    for book in books:  
       print(book)  
    
    3,自定义sql
    from django.db import connection  
      
    cursor = connection.cursor()  
    cursor.execute("insert into hello_author(name) VALUES ('郭敬明')")  
    cursor.execute("update hello_author set name='韩寒' WHERE name='郭敬明'")  
    cursor.execute("delete from hello_author where name='韩寒'")  
    cursor.execute("select * from hello_author")  
    cursor.fetchone()  
    cursor.fetchall() 

    ###############    ORM进阶    ################

    如何使用django orm批量创建数据
    使用django.db.models.query.QuerySet.bulk_create()批量创建对象,减少SQL查询次数。改进如下: querysetlist
    =[] for i in resultlist: querysetlist.append(Account(name=i)) Account.objects.bulk_create(querysetlist)

    ###############    ORM进阶    ################

     Django 三种模型继承:

    一 抽象类继承
    父类继承来自model.Model, 但不会在底层数据库生成相应的数据表,父类的属性列存储在其子类的数据表中
    作用:
    多个表若有相同的字段时,可以将这些字段统一定义在抽象类中,可以避免重复录入信息,
    要求:
    class BaseModel(models.Model):
     
        creat_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
        update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
        is_delete = models.BooleanField(default=False, verbose_name="是否删除")
     
        class Meta:
            abstract = True

    二 多表继承 每个模型类都会在底层数据库中生成相应的数据表管理数据 父类中的字段不会重复地在对个子类相关的数据表中进行定义
    from django import models class MessageBase(models.Model): id = models.AutoField() content = models.CharField(max_length=100) user_name= models.CharField(max_length=20) class Moment(MessageBase): headline = models.CharField(max_length=200) # Moment中包含的字段 id, headline # 子类可以直接引用父类定义的字段, 子类可以通过父类对象访问父类实例 三 代理模型继承 代理模型中子类只用于管理父类的数据,而不实际存储数据 使用原因: 子类中的新特性不会影响父类行为以及已有代码的行为 from django.db import models class Moment(models.Model): headline = models.CharField(max_length=200) user_name = models.CharField(max_legth=20) pub_date = models.DateField() class OrderedMoment(Moment): class Meta: proxy = True # 是否为代理模型 ordering = ["-pub_date"] #默认排序

    ###############    ORM进阶    ################

    selected_related与prefetch_related有什么区别?
    
    在Django中,所有的Queryset都是惰性的,意思是当创建一个查询集的时候,并没有跟数据库发生任何交互。
    
    因此我们可以对查询集进行级联的filter等操作,只有在访问Queryset的内容的时候,Django才会真正进行数据库的访问。
    
    而多频率、复杂的数据库查询往往是性能问题最大的根源。
    
    不过我们实际开发中,往往需要访问到外键对象的其他属性。如果按照默认的查询方式去遍历取值,那么会造成多次的数据库查询,效率可想而知。
        
    在查询对象集合的时候,把指定的外键对象也一并完整查询加载,避免后续的重复查询。
     
    1,select_related适用于外键和多对一的关系查询;
    2,prefetch_related适用于一对多或者多对多的查询。

    ###############    ORM进阶    ################


    ###############    ORM进阶    ################


    ###############    ORM进阶    ################


    ###############    ORM进阶    ################

  • 相关阅读:
    POJ 基本算法(3)
    给定范围的素数筛选(POJ 2689)
    无向图、有向图的最小环
    第k短路和A*
    HDU 4302 Holedox Eating (set + iterator)
    笛卡尔树
    HDU 多校联合第一场
    HDU 多校联合第二场
    POJ 图算法(3)
    POJ 1038 Bugs Integrated, Inc. (状态dp)
  • 原文地址:https://www.cnblogs.com/andy0816/p/12302026.html
Copyright © 2011-2022 走看看