在实际工作SQL语句中,使用到LEFT JOIN
、INNER JOIN
这种拼接语句是一个很常见的事儿,往往这种语句也很长,我昨天就写了一个80多行的一个语句。但是要知道Django的ORM语法跟Mysql的不一样,但是要在views.py里转用Django的写法来改写一个有join而且超长的语句就很麻烦,而且后期维护起来也很难。
那么遇到这种问题,一般有两种方式解决。
RAW方式
Manager.raw()方式,也就是说:
1
2
3
4
5from naxxramas.models import AAA # 假设有AAA这么一个models.py里的类做数据库结构
context["domains"] = AAA.objects.raw(
select * from XXX
#你的SQL语句直接粘贴过来就行,长语句的话,请搭配三个单引号使用
)
但是要注意,这个方法要求查询的时候必须要带primary key
,不然的话会报错django.db.models.query_utils.InvalidQuery: Raw query must include the primary key
。但是比如我原表的主键是id,而现在要在原表的基础上求和求差肯定不会select id...
,那么这里可以讨个巧,使用SELECT 1 as id,...
这样把id带进去但是写死,而在前端的时候,就放弃掉id即可。
使用DB-API方式
这就完全脱离ORM的范围了,直接使用了MySQLbd的api,举个例子如下:
1
2
3
4
5
6
7
8
9from django.db import connection
cursor = connection.cursor()
'''SELECT count(*) FROM people_person''') cursor.execute(
1L
row = cursor.fetchone()
print row
(12L,)
Person.objects.all().count()
12
其实我不推荐使用这种方式,代码看起来不伦不类的。
最后补充一下,如果要看一下ORM写法对应的sql写法是啥,就用query
,举个例子:
1
2
3
4True).values_list('name', flat=True) qs = Department.objects.filter(departmentvolunteer__isnull=
print(qs.query)
SELECT "app_department"."name" FROM "app_department" LEFT OUTER JOIN
"app_departmentvolunteer" ON ( "app_department"."id" = "app_departmentvolunteer"."department_id" ) WHERE "app_epartmentvolunteer"."id" IS NULL
这样可以帮你排查sql的问题。
参考资料
https://docs.djangoproject.com/zh-hans/3.2/topics/db/sql/
https://www.cnblogs.com/fmgao-technology/p/10119671.html