【问题标题】:Django raw query - connection.cursor() data is not showedDjango 原始查询 - 未显示 connection.cursor() 数据
【发布时间】:2020-01-02 11:05:21
【问题描述】:

当我使用 Table.objects.raw(raw query) 时,我可以看到数据。当我使用 connection.cursor()、cursor.execute(相同的原始查询)时,数据不会显示在 HTML 页面中。是什么原因?

甲骨文 11g CX-Oracle 7.2.2 Django 1.11.22

#ORM raw query - It's OK.
class UserList(ListView):
    query = 'select user_id, user_name from user'
    queryset = USER.objects.raw(query)
    context_object_name = 'user_list'
    template_name = 'user_list.html'

# Problem - data is not showed in screen.
class UserList(ListView):
    with connection.cursor() as cursor:
        cursor.execute('select user_id, user_name from user')
        queryset = cursor.fetchall()
        context_object_name = 'user_list'
        template_name = 'user_list.html'

#user_list.html
<h2>User List(ListView Sample)</h2>
<table border="1" align="center">
    <tr>        
        <th scope="col">User ID</th>
        <th scope="col">User Name</th>
    </tr>
    {% for user in user_list %}
    <tr>
        <th width="200"><a href="http://127.0.0.1:8000/sec/userlist/{{ user.id }}/">{{ user.user_id }}</a></th>
        <th width="200">{{ user.user_name }}</th>
    </tr>
    {% endfor %}
</table>

没有错误消息。但是数据没有显示在 HTML 页面中

【问题讨论】:

  • 使用.fetchall(..) 你确实不将结果解释为User 对象(在这种情况下)。但是首先使用原始查询实际上并不是一个好主意(使用硬编码的 URL 等也是如此)

标签: django


【解决方案1】:

这里有两个主要原因:

  1. QuerySet,甚至是raw(..),不急切地执行:它是懒惰地执行的。这意味着查询将在您呈现页面时运行。 Django 的ListView,每次都会复制查询集,因此每次获取对象时都会进行查询;和
  2. 通过使用Model.objects.raw(..),查询结果被解析为Model对象。通过执行.fetchall(),您检索的是元组列表,而不是模型对象列表。

但是,通常使用原始查询并不是一个好主意(都使用游标和Model.objects.raw(..)。模型不是表。模型是 Python 对象,有很多额外的逻辑来包装/解包值,并定义额外的对象。Django ORM 将进一步保护您免受您在模型中进行的小更改(例如在数据库端重命名列等)。此外,如果 ORM 实现正确,它不会生成不正确的查询语法等

因此建议使用ORM,因此写成:

class UserList(ListView):
    query = 'select user_id, user_name from user'
    queryset = USER.objects.all()
    context_object_name = 'user_list'
    template_name = 'user_list.html'

注意:Django模型的名称通常写成CamelCase,所以User而不是User。

【讨论】:

  • 感谢您的反馈。实际上,我想知道如何在 Django 程序中使用原始查询。如果我必须使用连接了许多表(超过 3 个表)的复杂选择查询,我该如何开发 django 程序?使用原始查询还是使用 ORM?
  • @Terry:通常使用原始查询是最后的手段,使用游标根本不是一个好主意。
  • 感谢您的反馈。但我需要使用复杂的查询,例如“START WITH CONNECT BY”。如何在 Django 程序中实现查询?
  • @Terry:通常这是通过以更好的方式对数据进行建模来完成的,例如使用django-mptt、django-treebeard、django-tree等。
  • 非常感谢。你的评论对我很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 2012-03-16
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 2018-05-15
相关资源
最近更新 更多