Django的raw方法执行SQL查询

  • 发布时间:2016年11月16日 10:36
  • 作者:杨仕航
  • 分类标签: Django
  • 阅读(16400)
  • 评论(0)

Django中模型查询可以用filter和get方法。但这些方法有时候远远不能满足我们的需求。

虽然有时候可以用__in,__icontains,__year和annotate,aggregate等拓展查询,但不灵活。

最灵活的方式还是使用SQL语句查询。

还好,Django也可以支持用SQL查询,并且可以返回对应的模型对象。


例如,有以下两个简单的模型:

Blog(博客):id, caption, content

Comment(评论):id, blog_id, comment

注意,id是Django模型的默认字段,无需在创建模型的时候,声明该字段。


先来个简单的查询,查询caption标题包含python的Blog。

若使用filter方法查询,如下:

blogs = Blog.objects.filter(caption__icontains = 'python')

filter方法得到的blogs,类型是QuerySet。

若使用SQL方法查询,如下:

sql = "select * from blog_blog where caption like '%python%'"
blogs = Blog.objects.raw(sql)

这里需要使用raw方法把sql语句转换成Blog对象,此处的blogs类型是RawQuerySet。

同样的效果,都可以查到caption标题包含python的记录。

也许,你会觉得raw方法执行sql语句要麻烦一些。还要查一下具体对应的表名。


那么再看看下一个查询:根据博客按照评论数倒序排序。

若用QuerySet方法,很复杂,需要用到annotate,并且还有联合Comment对象。至少我自己尝试写了几次都写不出来。

若用SQL方法查询,只需要懂得SQL联合查询和统计即可:

sql = """select blog_blog.* from blog_blog
    left join blog_comment
    on blog_blog.id = blog_comment.blog_id
    group by blog_blog.id
    order by count(blog_comment.id) desc
    """
blogs = Blog.objects.raw(sql)

blog_blog联合blog_comment表,再对blog_comment计数并倒序。


很明显,在复杂查询时,用原始的SQL查询有很明显的优势。

我们可以在简单查询的时候,用QuerySet方法。在复杂查询的时候,用SQL语句的方法。


使用SQL语句查询的raw方法有1个特点:SQL语句中的字段可以包含其他非该模型的字段,一样也会被解析成属性

例如,我按照评论数排序时,也想顺便得到评论数:

sql = """select blog_blog.*, count(blog_comment.id) as comment_num
    from blog_blog
      left join blog_comment
      on blog_blog.id = blog_comment.blog_id
    group by blog_blog.id
    order by count(blog_comment.id) desc
    """
blogs = Blog.objects.raw(sql)

这里的count(blog_comment.id) as comment_num 也会被解析成comment_num属性。

若把blogs返回给前端模版页面,我们可以在前端模版中直接读取该属性:

{% for blog in blogs %}
    标题:{{blog.caption}}
    评论数:{{blog.comment_num}}
{% endfor %}

这个便利性就不用我多说了。这个特性在开发过程中相当有用。

上一篇:Django一些有用的admin设置

下一篇:Excel工作表按照表名排序

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空