姜戈:哪几天有对象?

Django: Which days have objects?

我目前正在为我的一个 Django 项目创建一个简单的日历。日历将显示当前月份和日期。当天有商品的任何一天都将以红色突出显示,以便用户知道当天有商品。项目的数量或它们是什么项目并不重要。我们只关心一天有没有物品

假设我有以下模型。

class Items(models.Model):
    name = models.CharField(max_length=140)
    datetime = models.DateTimeField(auto_now_add=False)

    def save(self, *args, **kwargs):
        if datetim is None:
            created = datetime.now()
        super(Items, self).save()

这是我目前查找哪些天有物品的逻辑:

from calendar import monthrange

# Find number of days for June 2015

num_days = monthrange(2015, 6)[1]
days_with_items = []

'''
Increase num_days by 1 so that the last day of the month 
is included in the range
'''
num_days =+ 1

for day in range(0, num_days):
    has_items = Items.objects.filter(datetime__day = day,
                                     datetime__month = 6,
                                     datetime__year = 2015).exists()
    if has_items:
        days_with_items.append(day)
return days_with_items

这 returns 我列出了所有有项目的日子。这是可行的,但是我正在寻找一种更有效的方法来执行此操作,因为 Django 正在为 .exists()

多次访问数据库

有什么建议吗?

首先,让我们获取所需月份的所有项目。

items = Items.objects.filter(datetime__month=6, datetime__year=2015)
days = set([item.datetime.day for item in items]) # unique days

如果你想做部分查询,指定你需要的values,概念是这样的:

    items = Item.objects.filter(
        date_added__month=6, date_added__year=2015
    ).values('date_added')
    days = set([item['date_added'].day for item in items])

它将导致以下 SQL 查询:

QUERY = u'SELECT "main_item"."date_added" FROM "main_item" WHERE
(django_datetime_extract(\'month\', "main_item"."date_added", %s) = %s 
AND "main_item"."date_added" BETWEEN %s AND %s)' 
- PARAMS = (u"'UTC'", u'6', u'datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<UTC>)', 
            u'datetime.datetime(2015, 12, 31, 23, 59, 59, 999999, tzinfo=<UTC>)')

如果您要处理大量 Items,您可以将查询分成几部分(例如 < 15>=15)。这将导致额外的数据库命中,但内存使用率会变小。您还可以考虑不同的方法。

请注意:

  • datetime 不是字段的最佳名称。命名它 有意义的,例如:"date_added"、"date_created" 或类似的东西 那
  • if self.datetime is None 是 'almost' 等于 if not self.datetime

我看到两个可能的选择。第一个是在数据库级别添加计数,第二个是在 python 级别对可用数据进行有效循环。根据数据大小和数据库效率,您可以选择最适合您的。

数据库中的计数解释如下: Django ORM, group by day

或者解决方案二,一个简单的脚本(不是很优雅..但只是作为一个例子):

days_with_items_hash = {}
items = Items.objects.filter(
   datetime__month = 6, 
   datetime__year = 2015
)
for item in items:
    days_with_item_hash[item.datetime.day] = True

days_with_item = days_with_item_hash.keys()

我会坚持使用数据库解决方案,因为它可以优化(sql 视图、仅包含一天的额外列等)

使用dates方法。

items = Item.objects.filter(date_added__month=6, date_added__year=2015)
dates = items.dates('date_added', 'day') # returns a queryset of datetimes
days = [d.day for d in dates] # convert to a list of days