ORM执行原生SQL语句以及外部脚本使用Django的models

ORM执行原生SQL语句

下面的这篇博客有个例子是不能用ORM得出准确数据的(查找每个作者出版的所有书的最高价格以及那本书的名称):

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框架的东西~

解释图如下:

 

posted on 2019-05-29 18:34  江湖乄夜雨  阅读(421)  评论(0编辑  收藏  举报