Skip to main content
 首页 » 编程设计

python之使用 Django 获取具有尽可能接近日期的不同条目的查询集

2025年05月04日8emanlee

所以,我有一个看起来像这样的模型:

class Names(models.Model): 
  name = models.CharField() 
 
class Entries(models.Model): 
  name = models.ForeignKey(Names) 
  date = models.DateField() 

数据看起来像这样

name   |  date 
 
name_1 |  2011-06-01 
name_2 |  2011-03-01 
name_3 |  2011-02-01 
name_1 |  2010-06-01 
name_2 |  2010-03-02 
name_3 |  2010-02-01 
name_4 |  2009-07-01 

我想查询带有日期的条目,并在小于或等于日期的情况下获取每个姓名记录一次。所以,如果我查询日期 2011-06-01,我希望返回这个:

name_1 | 2011-06-01 
name_2 | 2011-03-01 
name_3 | 2011-02-01 
name_4 | 2009-07-01 

我的假设是这样可以解决问题:

date = datetime(year=2011, month=06, day=01) 
results = Entries.objects.filter(date__lte=date).order_by('date').distinct('name') 

但是,我一直在其中输入重复的名称。

friend 们有什么建议吗?

编辑:该解决方案由 Gareth Rees 提供。我不得不稍微修改一下,但它看起来像这样:

sql = """myapp_entries.id = (SELECT E.id from myapp_entries AS E 
                             WHERE E.name_id = myapp_names.id AND 
                             '"""+date.strftime('%Y-%m-%d')+"""' 
                             ORDER BY E.date DESC 
                             LIMIT 1)''' 
 
results = (Entries.objects 
           .extra(where = [sql]) 
           .filter(date__lte = date) 
           .order_by('name', 'date')) 

请您参考如下方法:

这里有几种方法,具体取决于您对结果的需求。

(1) 如果您不介意以字典形式获取结果(而不是 Entries 对象),那么您可以使用 annotate结合values对结果进行分组。在这种情况下,您想要的查询将是这样的:

from django.db.models import Min 
results = (Entries.objects 
           .filter(date__lte = date) 
           .values('name') 
           .annotate(date = Min('date')) 
           .order_by('name', 'date')) 

(2) 如果您需要将结果作为 Entries 对象返回,那么您可以使用 extra只选择所有同名条目中最早的条目:

sql = '''id = (SELECT E.id FROM myapp_entries AS E 
                WHERE E.name_id = myapp_entries.name_id 
                ORDER BY E.date 
                LIMIT 1)''' 
results = (Entries.objects 
           .extra(where = [sql]) 
           .filter(date__lte = date) 
           .order_by('name', 'date'))