【问题标题】:django paginate with non-model objectdjango 使用非模型对象分页
【发布时间】:2014-07-06 21:15:18
【问题描述】:

我正在使用 python 和 Django 进行一个辅助项目。它是一个网站,从某个网站跟踪某些产品的价格,然后显示产品的所有历史价格。

所以,我在 Django 中有这个类:

class Product(models.Model):
  price = models.FloatField()
  date = models.DateTimeField(auto_now = True)
  name = models.CharField()

然后,在我的views.py中,因为我想在表格中显示产品,像这样:

+----------+--------+--------+--------+--------+....
| Name     | Date 1 | Date 2 | Date 3 |...     |....
+----------+--------+--------+--------+--------+....
| Product1 | 100.0  | 120.0  | 70.0   | ...    |....
+----------+--------+--------+--------+--------+....
...

我正在使用以下类进行渲染:

class ProductView(objects):
  name = ""
  price_history = {}

因此,在我的模板中,我可以轻松地将每个 product_view 对象转换为一个表格行。我还在上下文中传递了所有可用日期的排序列表,目的是构建表格的头部,并获取该日期每个产品的价格。

然后我在将一个或多个产品转换为这个 ProductView 对象的视图中有逻辑。逻辑看起来像这样:

def conversion():
  result_dict = {}
  all_products = Product.objects.all()
  for product in all_products:
    if product.name in result_dict:
      result_dict[product.name].append(product)
    else:
      result_dict[product.name] = [product]
  # So result_dict will be like 
  # {"Product1":[product, product], "Product2":[product],...}
  product_views = []
  for products in result_dict.values():
    # Logic that converts list of Product into ProductView, which is simple.
  # Then I'm returning the product_views, sorted based on the price on the 
  # latest date, None if not available.
  return sorted(product_views, 
                key = lambda x: get_latest_price(latest_date, x),
                reverse = True)

根据 Daniel Roseman 和 zymud,添加 get_latest_price:

def get_latest_price(date, product_view):
  if date in product_view.price_history:
    return product_view.price_history[date]
  else:
    return None

我省略了获取最新转换日期的逻辑。我有一个单独的表,它只记录我运行价格收集脚本的每个日期,该脚本将新数据添加到表中。所以获取最新日期的逻辑本质上是获取 OpenDate 表中 ID 最高的日期。

所以,问题是,当产品增长到巨大的数量时,我如何对 product_views 列表进行分页?例如如果我想在我的 Web 应用程序中查看 10 个产品,如何告诉 Django 只从 DB 中获取这些行?

我不能(或不知道如何)使用 django.core.paginator.Paginator,因为要创建我想要的 10 行,Django 需要选择与这 10 个产品名称相关的所有行。但要确定选择哪 10 个名称,首先需要获取所有对象,然后找出最近日期价格最高的对象。

在我看来,唯一的解决方案是在 Django 和 DB 之间添加一些东西,比如缓存,以存储 ProductView 对象。但除此之外,有没有办法直接对 produvt_views 列表进行分页?

【问题讨论】:

  • 你可以对查询中的产品进行排序,而不是将它们排序为 product_views 吗?
  • 您需要将排序逻辑移动到数据库中。 get_latest_price 是什么?也许可以通过注释或原始 SQL 来完成。
  • 嘿 Daniel 和 zymud,我已经编辑了帖子以包含 get_latest_price 的逻辑。如您所见,我正在尝试按赋予该功能的最新日期的价格对列表进行排序。因此我认为我不能在数据库中对其进行排序,对于那些在“最新日期”不可用的产品,它们将位于底部,因此在获取列表构造 ProductView 对象时不会包含它们.

标签: django django-models pagination django-views


【解决方案1】:

我想知道这是否有意义:

基本的想法是,因为我需要按“最新”日期的价格对所有 product_views 进行排序,所以我会先在 DB 中执行该操作,并且只获取产品名称列表以使其“可分页” ”。然后,我将进行第二次数据库查询,以获取具有这些产品名称的所有产品,然后构造那么多 product_views。有意义吗?

为了清楚一点,这里是代码:

所以不是

#def conversion():
  all_products = Product.objects.all()

我正在这样做:

#def conversion():
  # This would get me the latest available date
  latest_date = OpenDate.objects.order_by('-id')[:1]
  top_ten_priced_product_names = Product.objects
      .filter(date__in = latest_date)
      .order_by('-price')
      .values_list('name', flat = True)[:10]
  all_products_that_i_need = Product.objects
      .filter(name__in = top_ten_priced_product_names)
  # then I can construct that list of product_views using
  # all_products_that_i_need

然后对于第一页之后的页面,我可以将 [:10] 修改为 [10:10] 或 [20:10]。

这使得代码分页更容易,并且通过将适当的代码拉入一个单独的函数,也可以执行 Ajax 和所有那些花哨的东西。

但是,问题来了:这个解决方案需要为每个查询调用三个数据库。现在我在同一个盒子上运行所有东西,但我仍然想将这个开销减少到两个(一个或 Opendate,另一个用于产品)。

有没有更好的解决方案可以同时解决分页问题和两个数据库调用?

【讨论】:

    猜你喜欢
    • 2018-09-13
    • 2010-11-24
    • 2014-11-19
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2013-01-26
    • 2012-12-26
    • 2021-10-30
    相关资源
    最近更新 更多