ORM执行原生SQL语句以及外部脚本使用Django的models
ORM执行原生SQL语句
下面的这篇博客有个例子是不能用ORM得出准确数据的(查找每个作者出版的所有书的最高价格以及那本书的名称):
也就是说,在ORM模型查询API不够用的情况下,我们只能使用原始的SQL语句进行查询。
Django提供两种方法使用原始SQL进行查询:
一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。
raw()方法
raw()管理器方法用于原始的SQL查询,并返回模型的实例。
需要注意的是~raw()语法查询必须包含主键。
这个方法执行原始的SQL查询,并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样,通过迭代来提供对象实例。
利用raw方法执行原生的SQL语句
还拿上面那个链接的例子来说:
我们先为Book类中加一个__str__方法:
class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=33) price = models.DecimalField(max_digits=8,decimal_places=2) ups = models.IntegerField(default=3) comments = models.IntegerField(default=1) publisher = models.ForeignKey(to='Publish',to_field='id',on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') def __str__(self): return self.title
然后增加一条测试路由:
url(r'^raw/',views.raw),
然后使用raw方法:
for book_obj in Book.objects.raw('select * from book_book where price>100'): print(book_obj)
结果为两个书籍对象(因为__str__方法返回书籍的title~因此打印的结果是书籍的title):
go
ruby
raw()查询可以查询其他表的数据
#注意这里必须有id字段~否则会报错 ret = Book.objects.raw('select id,city from book_publish') for i in ret: print(i.id,i.city)
结果是Publish表的id与city~注意必须要select id,否则会报错!
raw()方法自动将查询字段映射到模型字段
还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典
dic = {'city':'C'} ret = Book.objects.raw('select * from book_publish',translations=dic) for i in ret: print(i.id,i.name,i.C)
结果为:
21 苹果出版社 北京 22 橘子出版社 上海 23 樱桃出版社 成都 24 西瓜出版社 包头 25 橙子出版社 呼和浩特
原生SQL还可以使用参数,注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!
注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!
dic = {'city':'C'} ret = Book.objects.raw('select * from book_publish where id > %s',translations=dic,params=[22,]) for i in ret: print(i.id,i.name,i.C)
结果为:
23 樱桃出版社 成都 24 西瓜出版社 包头 25 橙子出版社 呼和浩特
直接执行自定义SQL
有时候raw()方法并不十分好用,很多情况下我们不需要将查询结果映射成模型,或者我们需要执行DELETE、 INSERT以及UPDATE操作。
在这些情况下,我们可以直接访问数据库,完全避开模型层。
我们可以直接从django提供的接口中获取数据库连接,然后像使用pymysql模块一样操作数据库。
这里直接省略路由与视图函数的创建~直接上代码~
注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!
from django.db import connection,connections
cursor = connection.cursor() #cursor = connections['default'].cursor()
cursor.execute(' select * from book_publish where id > %s ',[22])
ret = cursor.fetchall()
print(ret)
结果为:
((23, '樱桃出版社', '成都'), (24, '西瓜出版社', '包头'), (25, '橙子出版社', '呼和浩特'))
文章一开始链接的那个不能用ORM做的题也可以用这种直接执行原生SQL的方式实现:
from django.db import connection,connections cursor = connection.cursor() cursor.execute(''' select title,price from (select * from (select title,price,author_id from book_book inner join book_book_authors on book_book.id = book_book_authors.book_id )as t1 inner join book_author on t1.author_id=book_author.id group by name) as t2 order by t2.id ''') ret = cursor.fetchall() print(ret)
结果为:
(('c', Decimal('56.23')), ('linux', Decimal('12.23')), ('linux', Decimal('12.23')), ('rsb', Decimal('51.23')), ('c', Decimal('56.23')), ('cpp', Decimal('14.23')), ('xsd', Decimal('12.23')), ('c', Decimal('56.23')), ('python', Decimal('22.23')))
外部脚本使用Django的models
如果你想通过自己创建的python文件在django项目中使用django的models,那么就需要调用django的环境:
# -*- coding:utf-8 -*-
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "MultiTables.settings")
import django
django.setup()
# 注意引入要在上面三句之后
from book.models import *
ret = Publish.objects.all()
print(ret)
其实~manage.py文件中一开始也是这样写的~首先进入Django环境~才能用Django框架的东西~
解释图如下: