• Django models对象的select_related方法(减少查询次数)


    表结构

    先创建一个新的app
    python manage.py startapp test01
    在settings.py注册一下app

    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'test01',
    )
    

    models.py

    from django.db import models
    
    class Person(models.Model):
        name = models.CharField('作者姓名', max_length=10)
        age = models.IntegerField('作者年龄')
    
    
    class Book(models.Model):
        person = models.ForeignKey(Person, related_name='person_book')
        title = models.CharField('书籍名称', max_length=10)
        pubtime = models.DateField('出版时间')
    

    执行如下2条语句初始化表结构

    python manage.py makemigrations
    python manage.py migrate
    

    两张表关系说明:
    一个人员表,一个书名表,人员有字段name和age,书名表的人员和人员表外键关联,即一本书的作者只能有一个,一个作者可以有多本书

    打开sql执行过程日志到console中

    # 通过此方法可以看到django ORM的详细执行过程
    # 在项目的settings.py中添加如下内容
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
            }
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'level': 'DEBUG',
            },
        }
    }
    

    然后就通过数据库或者admin随便插入几条数据吧,admin这里就不赘述了

    在console里测试一下效果吧

    # 先看看不用select_related的效果,通过书来找到书作者的名字,子表找母表的一个字段
    >>> b=models.Book.objects.get(id=1)
    (0.000) QUERY = u'SELECT "test01_book"."id", "test01_book"."person_id", "test01_book"."title", "test01_book"."pubtime" FROM "test01_book" WHERE "test01_book"."id" = %s' - PARAMS = (1,); args=(1,)
    >>> print b.person.name
    王八
    (0.000) QUERY = u'SELECT "test01_person"."id", "test01_person"."name", "test01_person"."age" FROM "test01_person" WHERE "test01_person"."id" = %s' - PARAMS = (1,); args=(1,)
    # 效果就是查询了2次数据库
    
    # 再来看看用了select_related的效果
    >>> b=models.Book.objects.select_related().get(id=1)
    (0.000) QUERY = u'SELECT "test01_book"."id", "test01_book"."person_id", "test01_book"."title", "test01_book"."pubtime", "test01_person"."id", "test01_person"."name", "test01_person"."age" FROM "test01_book" INNER JOIN "test01_person" ON ( "test01_book"."person_id" = "test01_person"."id" ) WHERE "test01_book"."id" = %s' - PARAMS = (1,); args=(1,)
    >>> print b.person.name
    王八
    # 只查询了一次数据库,当然会提高性能,orm在第一次拿出book对象的时候,就顺道把他关联的表的信息拿到了,所以第二次就不用再重新查询了,类似一个信息的缓存,同理一对一关联也可以这么做
    
    # select_related()可以接一个参数,比如book这张表除了person还有public一个字段也是外键,那么可以在()内指定'person',即可只取到person关联的,即如下3行,最后执行的sql是不同的,以免获取到大量不用的信息浪费性能
    b = models.Book.objects.select_related().get(id=1)
    In[4]: b = models.Book.objects.select_related('public').get(id=1)
    In[5]: b = models.Book.objects.select_related('person').get(id=1)
    
  • 相关阅读:
    点击图片显示原图
    SQL判断语句
    窗口淡入淡出效果
    判断两段时间之间的时间差
    软件行业发展趋势
    VSS客户端不能访问问题“unable to open user login file\\服务器项目管理目录\data\logedin\用户名.log ”
    鑫哥儿子顺利降生了!
    面向对象原则之单一职责原则实现
    PHP编码,乱码问题
    泛型中的default(T)
  • 原文地址:https://www.cnblogs.com/caseast/p/5821216.html
Copyright © 2020-2023  润新知