【问题标题】:Is it possible to filter on a related item in Django annotations?是否可以过滤 Django 注释中的相关项目?
【发布时间】:2009-08-18 06:09:56
【问题描述】:

我有以下两种型号:

class Job(models.Model):
    title = models.CharField(_('title'), max_length=50)
    description = models.TextField(_('description'))
    category = models.ForeignKey(JobCategory, related_name='jobs')
    created_date = models.DateTimeField(auto_now_add=True)

class JobCategory(models.Model):
    title = models.CharField(_('title'), max_length=50)
    slug = models.SlugField(_('slug'))

到目前为止,这是我的查询所在:

def job_categories():
    categories = JobCategory.objects.annotate(num_postings=Count('jobs'))
    return {'categories': categories}

问题是我只想计算过去 30 天内创建的工作。但是,我想返回所有类别,而不仅仅是那些具有合格工作的类别。

【问题讨论】:

    标签: python django annotations django-queryset


    【解决方案1】:

    只是一个猜测......但这会起作用吗?

    def job_categories():
        thritydaysago = datetime.datetime.now() - datetime.timedelta(days=30)
        categories = JobCategory.objects.filter(job__created_date__gte=thritydaysago).annotate(num_postings=Count('jobs'))
        return {'categories': categories}
    

    有关跨越查询的更多详细信息,请参阅“lookups-that-span-relationships”。 嗯...可能需要另一个查询来获取所有类别...

    【讨论】:

    • 这将仅返回在过去 30 天内创建了作业的类别。我还试图避免返回多个查询集,因为这违背了使用注释的目的。这个函数实际上作为一个模板标签存在,我希望在模板层包含每个类别的计数(即使计数为 0)。不过谢谢。
    • 是的,我认为您只需要执行两个查询。
    【解决方案2】:

    我决定以不同的方式处理这个问题,并选择根本不使用注释。我在 Job 模型中添加了一个管理器,它只返回活动(30 天或更短的旧)作业,并在 JobCategory 模型上创建了一个属性,用于查询实例的作业计数。我的模板标签只是返回了所有类别。这是相关代码。

    class JobCategory(models.Model):
        title = models.CharField(_('title'), max_length=50, help_text=_("Max 50 chars. Required."))
        slug = models.SlugField(_('slug'), help_text=_("Only letters, numbers, or hyphens. Required."))
    
        class Meta:
            verbose_name = _('job category')
            verbose_name_plural = _('job categories')
    
        def __unicode__(self):
            return self.title
    
        def get_absolute_url(self):
            return reverse('djobs_category_jobs', args=[self.slug])
    
        @property
        def active_job_count(self):
            return len(Job.active.filter(category=self))
    
    class ActiveJobManager(models.Manager):
        def get_query_set(self):
            return super(ActiveJobManager, self).get_query_set().filter(created_date__gte=datetime.datetime.now() - datetime.timedelta(days=30))
    
    class Job(models.Model):
        title = models.CharField(_('title'), max_length=50, help_text=_("Max 50 chars. Required."))
        description = models.TextField(_('description'), help_text=_("Required."))
        category = models.ForeignKey(JobCategory, related_name='jobs')
        employment_type = models.CharField(_('employment type'), max_length=5, choices=EMPLOYMENT_TYPE_CHOICES, help_text=_("Required."))
        employment_level = models.CharField(_('employment level'), max_length=5, choices=EMPLOYMENT_LEVEL_CHOICES, help_text=_("Required."))
        employer = models.ForeignKey(Employer)
        location = models.ForeignKey(Location)
        contact = models.ForeignKey(Contact)
        allow_applications = models.BooleanField(_('allow applications'))
        created_date = models.DateTimeField(auto_now_add=True)
    
        objects = models.Manager()
        active = ActiveJobManager()
    
        class Meta:
            verbose_name = _('job')
            verbose_name_plural = _('jobs')
    
        def __unicode__(self):
            return '%s at %s' % (self.title, self.employer.name)
    

    还有标签...

    def job_categories():
        categories = JobCategory.objects.all()
        return {'categories': categories}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 2020-12-23
      相关资源
      最近更新 更多