• Django ORM的骚操作


    1. Django ORM执行原生SQL
    在模型查询API不够用的情况下,我们还可以使用原始的SQL语句进行查询。

    Django 提供两种方法使用原始SQL进行查询:一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。

    • 执行原生查询
      raw()管理器方法用于原始的SQL查询,并返回模型的实例:

    注意:raw()语法查询必须包含主键。

    这个方法执行原始的SQL查询,并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样,通过迭代来提供对象实例。

    例如:

    class Person(models.Model):
        first_name = models.CharField(...)
        last_name = models.CharField(...)
        birth_date = models.DateField(...)

    可以像下面这样执行原生sql语句:

    >>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
    ...     print(p)

    raw()查询可以查询其他表的数据。
    举个例子:

    ret = models.Student.objects.raw('select id, tname as hehe from app02_teacher')
        for i in ret:
            print(i.id, i.hehe)

    raw()方法自动将查询字段映射到模型字段。还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典

    d = {'tname': 'haha'}
        ret = models.Student.objects.raw('select * from app02_teacher', translations=d)
        for i in ret:
            print(i.id, i.sname, i.haha)

    原生SQL还可以使用参数,注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!

    d = {'tname': 'haha'}
        ret = models.Student.objects.raw('select * from app02_teacher where id > %s', translations=d, params=[1,])
        for i in ret:
            print(i.id, i.sname, i.haha)
    • 直接执行自定义SQL
      有时候raw()方法并不十分好用,很多情况下我们不需要将查询结果映射成模型,或者我们需要执行DELETE、 INSERT以及UPDATE操作。在这些情况下,我们可以直接访问数据库,完全避开模型层。

    我们可以直接从django提供的接口中获取数据库连接,然后像使用pymysql模块一样操作数据库。

    from django.db import connection, connections
    cursor = connection.cursor()  # cursor = connections['default'].cursor()
    cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    ret = cursor.fetchone()

    2. Django终端打印SQL语句
    在Django项目的settings.py文件中,在最后复制粘贴如下代码:

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

    3. 在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)

    Django 的查询语法难以简单的表达复杂的 WHERE 子句,对于对于这种情况, Django 提供了 extra() 方法。 extra() 能在 QuerySet 生成的SQL从句中注入新子句,这样可以完成复制的查询。

    extra()

    extra 方法的源码在 models/query.py 查看

     def extra(self, select=None, where=None, params=None, tables=None,
                  order_by=None, select_params=None):
            """Add extra SQL fragments to the query."""
            assert self.query.can_filter(), 
                "Cannot change a query once a slice has been taken"
            clone = self._chain()
            clone.query.add_extra(select, select_params, where, params, tables, order_by)
            return clone

    详细使用:

    https://cloud.tencent.com/developer/article/1656690

    djagon orm的一些其他用法:

    https://django-orm-cookbook-zh-cn.readthedocs.io/zh_CN/latest/f_query.html

    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    android模拟器速度问题
    input.nextLine() 问题出错!
    android中的“visible ”、“invisible”、“gone”的区别(转载)
    为什么匿名内部类参数必须为final类型(转载)
    转载------------------关于android的一些技巧
    关于数据库的数据类型
    关于几个新的快捷键
    目标

    巨大bug
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/15123625.html
Copyright © 2020-2023  润新知