【问题标题】:Django retrieve data from database to templateDjango 从数据库中检索数据到模板
【发布时间】:2016-09-08 09:53:45
【问题描述】:

我在从数据库中检索数据时遇到问题, 我正在使用 Mysql 数据库和一个包含 15 个字段的表,我将在表中的模板上显示它。

表中有超过400万条记录,

def index(request):
    args = {}
    data = Mymodel.objects.all()
    args['data'] = data
    return render(request, 'index.html', args)

我尝试过这种方式,但数据加载非常缓慢,

我为数据库连接尝试的下一种方法

def index(request):
    args = {}
    sql = "select * from mymodel"
    cursor = connection.cursor()
    cursor.execute(sql)
    result = cursor.fetchall()
    args['result'] = result
    return render(request, 'index.html', args)

这也是一样的,我需要更快地加载数据。请向我建议任何可以更快加载数据的方法。

【问题讨论】:

  • 您正在尝试显示 400 万条记录,它永远不会很快,您需要决定您实际需要显示什么
  • 请看一下 Django 的分页 API:docs.djangoproject.com/en/1.9/topics/pagination
  • 分页是加快速度的最佳方式。查询然后尝试显示 400 万条记录是不可取的。

标签: mysql django


【解决方案1】:

解决方案之前的一个概念修正是,使用原始 sql 并不比 django ORM 做得更好,而且您也失去了使用 ORM api 轻松显示数据的能力。

常见的解决方案是使用 django 内置的分页功能,每页只显示一定数量的记录。 Django doc对分页的使用有非常详细的解释。

【讨论】:

  • "... 使用原始 sql 并没有比 django ORM 做得更好" ORM 确实增加了一些开销(尤其是内存开销),这通常是可以接受的权衡,但可以在这些情况下出现问题。
  • @fabio.sussetto - 你在说什么开销?它不在数据库方面,因为它归结为相同的查询,并且它不能用于检索结果,因为您也需要以相同的方式进行操作。因此,如果您谈论的是 sql 查询的创建,那么这就是无稽之谈,因为它不是密集的,而且对于 objects.all() 来说绝对不是密集的。我还没有找到原始查询的需求。
  • 必须创建所有模型实例对象确实有开销,而不是使用 cursor.fetchall() 返回元组
  • @fabio.sussetto 也许我的措辞有点绝对,但我想告诉 OP,与其他操作相比,开销是如此之小以至于可以忽略,因此没有必要尝试.
  • @ShangWang 我同意你的观点,OP 的想法几乎是从 IMO 开始的一个失败的原因:) 我的意思是要澄清,如果你想挤出性能,在某些情况下绕过ORM 可能是您唯一的解决方案。
【解决方案2】:

由于您已经在执行原始查询,我认为您实际上不会比现有的查询做得更好。

有什么原因不能对结果进行分页吗?通常你永远不会返回所有可用的数据。

您可以尝试使用 QuerySet.iterator 来避免一次将所有实例加载到内存中。此外,QuerySet.values 将返回字典而不是完整的模型实例,从而减少内存使用。

如果您绝对需要并且遇到请求超时,一种选择是在后台运行实际的数据检索。例如,您可以使用 Celery 并将查询作为任务的一部分运行。您的视图将触发 Celery 任务并在响应中返回任务标识符。然后,消费者可以轮询传递此类任务 ID 的“作业状态”端点,并在它们准备好时检索结果。您仍然需要将结果存储在比您的数据库(更快)的其他地方,即 Redis(您可以轻松地将其用作 Celery 后端)。

这种方法显然更加复杂,并且会在您的系统中添加一些移动部件,而且您很可能会遇到其他问题(例如响应大小)。如果可能的话使用分页会容易得多。

【讨论】:

    【解决方案3】:

    如果您希望系统处理数千条记录,则可以使用分页。在这种情况下,Django 通用 ListView 将为您提供帮助。它们易于使用。他们是这样工作的

    class YourView(ListView):
        template_name = 'books/acme_list.html'
        context_object_name = 'object_list'
        queryset = TableName.objects.all()
        paginate_by = 50
    

    你的模板会是这样的

    <table id="exam">
      {% for object in object_list %}
      <tr>
        <td>{{ object }}</td>
      </tr>
      {% endfor %}
    </table>
    

    你的分页部分会是这样的

    {% if is_paginated %}
      <ul class="pagination">
        {% if page_obj.has_previous %}
          <li>
             <span><a href="?page={{ page_obj.previous_page_number }}">Previous</a></span>
         </li>
        {% endif %}
          <li class="">
            <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
          </li>
        {% if page_obj.has_next %}
          <li>
            <span><a href="?page={{ page_obj.next_page_number }}">Next</a></span>
          </li>
        {% endif %}
          </ul>
    {% endif %}
    

    您可以在此 link 和 Django 文档中找到更多详细信息。

    【讨论】:

    • 添加您的建模方式以显示返回多个对象以及使用 def __str__(self):
    猜你喜欢
    • 2013-07-26
    • 1970-01-01
    • 2020-09-24
    • 2014-07-15
    • 2017-04-07
    • 1970-01-01
    • 2011-01-28
    • 2013-05-11
    • 1970-01-01
    相关资源
    最近更新 更多