2009-08-18 4 views
1

Ich habe folgende 2 Modelle:Ist es möglich, in Django-Annotationen nach einem verwandten Element zu filtern?

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')) 

Hier ist, wo ich mit der Abfrage bin so weit:

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

Das Problem ist, dass ich möchte nur Arbeitsplätze zählen, die in die erstellt wurden, nach 30 Tagen. Ich möchte jedoch alle Kategorien zurückgeben, nicht nur jene Kategorien, die qualifizierte Jobs haben.

Antwort

1

Ich entschied mich, anders anzugehen und wählte keine Anmerkungen überhaupt zu verwenden. Ich habe dem Jobmodell einen Manager hinzugefügt, der nur aktive Jobs (30 Tage oder weniger alt) zurückgegeben hat, und eine Eigenschaft im JobCategory-Modell erstellt, die nach der Jobanzahl der Instanz abgefragt wurde. Mein TemplateTag hat einfach alle Kategorien zurückgegeben. Hier ist der relevante 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) 

und den Tag ...

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

Nur eine Vermutung ... aber würde das funktionieren?

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} 

Siehe "lookups-that-span-relationships" für weitere Details über Spanning Abfragen. Hmmm ... wahrscheinlich brauchen Sie eine andere Abfrage dort, um alle Kategorien zu bekommen ...

+1

Dies ist nur die Kategorien angezeigt werden kann, die in den letzten 30 Tagen Arbeitsplätze geschaffen haben. Ich versuche auch, die Rückgabe mehrerer Abfragegruppen zu vermeiden, da dies dem Zweck der Verwendung von Anmerkungen widerspricht. Diese Funktion existiert tatsächlich als TemplateTag, und ich hatte gehofft, in der Template-Ebene die Zählungen mit jeder der Kategorien einzuschließen (selbst wenn der Zählwert 0 ist). Trotzdem danke. – gsiegman

+0

Ja, ich denke, Sie müssen nur zwei Abfragen durchführen. – monkut