python测试开发django-78.ORM查询之extra

Posted 上海-悠悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python测试开发django-78.ORM查询之extra相关的知识,希望对你有一定的参考价值。

前言

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

select 参数

select参数可以让你在 SELECT 从句中添加其他字段信息,它传一个字典

SELECT age, (age>15) as is_age FROM yoyo_personinfo;

is_age 返回的是一个布尔值

django查询的示例:

PersonInfo.objects.all().extra(select={\'is_age\': "age > 18"}).values(\'age\',\'is_age\')

# 作者-上海悠悠 QQ交流群:717225969
MyDjango>python manage.py shell
>>> from yoyo.models import PersonInfo
>>>
>>> PersonInfo.objects.all().extra(select={\'is_age\': "age > 18"}).values(\'age\',\'is_age\')
<QuerySet [{\'is_age\': 1, \'age\': 20}, {\'is_age\': 0, \'age\': 11}, 
{\'is_age\': 1, \'age\': 20}, {\'is_age\': 1, \'age\': 20}, 
{\'is_age\': 0, \'age\': 11}, {\'is_age\': 0, \'age\': 11}]>

跟上面的查询效果是一样的

where 参数

可以使用 where 定义显式SQL WHERE子句,这样可以处理复杂的 WHERE 条件语句

SELECT * from yoyo_personinfo WHERE age in (20, 21) and name LIKE \'yoyo%\';

django 查询的示例, where 传的是 list 类型参数:

>>> PersonInfo.objects.all().extra(where=["age in (20, 21) and name LIKE \'yoyo%%\'"]).values("age", "name")
<QuerySet [{\'age\': 20, \'name\': \'yoyo2\'}, {\'age\': 20, \'name\': \'yoyo4\'}, {\'age\': 21, \'name\': \'yoyo5\'}]>
>>>

and 的多个条件也可以逗号分成多个参数 where=["age in (20, 21)", "name LIKE \'yoyo%%\'"])

>>> PersonInfo.objects.all().extra(where=["age in (20, 21)", "name LIKE \'yoyo%%\'"]).values("age", "name")
<QuerySet [{\'age\': 20, \'name\': \'yoyo2\'}, {\'age\': 20, \'name\': \'yoyo4\'}, {\'age\': 21, \'name\': \'yoyo5\'}]>

table 参数

table 参数用于多表联合查询的时候,加到 FROM 后面
如果我想把2个表的数据查询结果放到一张表

使用 SQL 语句为

SELECT * from yoyo_card, yoyo_personinfo WHERE card_user=name;

查询的结果

django 查询的示例,table传list参数,可以是多个表名称,如:table=[\'yoyo_personinfo\']

Card.objects.all().extra(tables=[\'yoyo_personinfo\'], where=[\'card_user=name\']).values()

# 作者-上海悠悠 QQ交流群:717225969
MyDjango>python manage.py shell
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from yoyo.models import Card,PersonInfo
>>> 
>>> Card.objects.all().extra(tables=[\'yoyo_personinfo\'], where=[\'card_user=name\']).values()
<QuerySet [{\'id\': 2, \'card_id\': \'520000000001\', \'card_user\': \'yoyo2\', \'add_time\': datetime.datetime(2020, 6, 22, 22, 34, 14)}, 
{\'id\': 9, \'card_id\': \'800080007\', \'card_user\': \'yoyo3\', \'add_time\': datetime.datetime(2020, 6, 28, 22, 15, 34)}]>
>>>

params添参数

错误的方式 !!

first_name = \'Joe\'  # 如果first_name中有SQL特定字符就会出现漏洞
Person.objects.all().extra(where=["first = \'%s\'" % first_name])

正确方式

Person.objects.all().extra(where=["first = \'%s\'"], params=[first_name])

以上是关于python测试开发django-78.ORM查询之extra的主要内容,如果未能解决你的问题,请参考以下文章

python测试开发django(12)--ORM查询表结果

python测试开发django-80.ORM查询之比较查询(__gt, __lt)

python测试开发django-15.查询结果转json(serializers)

python测试开发django-37.外键(ForeignKey)查询

python测试开发django-15.查询结果转json(serializers)

python测试开发django-170.ORM查询之contains和icontains