Reputation: 1151
I have the following 2 models:
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'))
Here is where I am at with the query thus far:
def job_categories():
categories = JobCategory.objects.annotate(num_postings=Count('jobs'))
return {'categories': categories}
The problem is that I only want to count jobs that were created in the past 30 days. I want to return all categories however, not only those categories that have qualifying jobs.
Upvotes: 1
Views: 1434
Reputation: 43832
Just a guess... but would this work?
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}
See"lookups-that-span-relationships" for more details on spanning queries. Hmmm... probably need another query in there to get all categories...
Upvotes: 4
Reputation: 1151
I decided to approach this differently and chose not to use annotations at all. I added a manager to the Job model that returned only active (30 days or less old) jobs, and created a property on the JobCategory model that queried for the instance's job count. My templatetag simply returned all categories. Here is the relevant code.
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)
and the tag...
def job_categories():
categories = JobCategory.objects.all()
return {'categories': categories}
Upvotes: 1