2010-01-25 8 views
5

Sto tentando di creare una pagina profilo che mostra la quantità di nani assegnati a ciascuna carriera corrispondente. Ho 4 carriere, 2 posti di lavoro all'interno di ciascuna di quelle carriere e, naturalmente, molti nani che hanno ciascuno un singolo lavoro. Come posso ottenere un conteggio del numero di nani in ciascuna di queste carriere? La mia soluzione era quella di mettere a fuoco i nomi di carriera nell'HTML e di fare una query per ogni carriera, ma sembra una quantità eccessiva di domande.Django: più COUNT da due modelli di distanza

Ecco quello che "voglio" vedere:

Unassigned: 3 
Construction: 2 
Farming: 0 
Gathering: 1 

Ecco i miei modelli. Aggiungo un po 'di complessità non collegando le carriere direttamente al mio modello di Dwarves (che sono collegati dai loro lavori).

from django.contrib.auth.models import User 
from django.db import models 

class Career(models.Model): 
    name = models.CharField(max_length = 64) 

    def __unicode__(self): 
     return self.name 

class Job(models.Model): 
    career = models.ForeignKey(Career) 
    name = models.CharField(max_length = 64) 
    career_increment = models.DecimalField(max_digits = 4, decimal_places = 2) 
    job_increment = models.DecimalField(max_digits = 4, decimal_places = 2) 

    def __unicode__(self): 
     return self.name 

class Dwarf(models.Model): 
    job = models.ForeignKey(Job) 
    user = models.ForeignKey(User) 
    created = models.DateTimeField(auto_now_add = True) 
    modified = models.DateTimeField(auto_now = True) 
    name = models.CharField(max_length = 64) 

    class Meta: 
     verbose_name_plural = 'dwarves' 

    def __unicode__(self): 
     return self.name 

EDIT 1 mio punto di vista sembra qualcosa di simile:

def fortress(request): 
    careers = Career.objects.annotate(Count('dwarf_set')) 
    return render_to_response('ragna_base/fortress.html', {'careers': careers}) 

e il modello:

{% for career in careers %} 
    <li>{{ career.dwarf_set__count }}</li> 
{% endfor %} 

L'errore è:

Cannot resolve keyword 'dwarf_set' into field. Choices are: id, job, name 

SOLUZIONE

vista:

def fortress(request): 
    careers = Career.objects.all().annotate(dwarfs_in_career = Count('job__dwarf')) 
    return render_to_response('ragna_base/fortress.html', {'careers': careers}) 

modello:

{% for career in careers reversed %} 
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li> 
{% endfor %} 

ANCORA MEGLIO SOLUZIONE

careers = Career.objects.filter(Q(job__dwarf__user = 1) | Q(job__dwarf__user__isnull = True)) \ 
    .annotate(dwarves_in_career = Count('job__dwarf')) 

Non dimenticate di from django.db.models import Count, Q

Quello che mi piace della soluzione di cui sopra è che non solo restituisce le carriere che hanno i nani al lavoro, ma anche le carriere che non ne hanno che è stato il prossimo problema che ho incontrato. Ecco il mio punto di vista per completezza:

<ul> 
{% for career in careers %} 
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li> 
{% endfor %} 
</ul> 

risposta

1

Fa questo ciò che vuoi?

from django.db.models import Count 
Career.objects.annotate(Count('dwarf')) 

Ora ogni oggetto career dovrebbe avere una proprietà dwarf__count.

+0

Non male! Continuo a ricevere l'errore: Impossibile risolvere la parola chiave 'dwarf_set' nel campo. Le scelte sono: id, job, name Ma sto provando cose diverse. – TheLizardKing

+0

Credo che funzionerebbe se il mio modello di Dwarf fosse direttamente correlato al mio modello di carriera, ma ho scelto di collegare i due tramite il mio modello di lavoro per consentire l'alterazione delle carriere. – TheLizardKing

1

può non solo ottenere un conteggio raggruppati per carriera? E fai un join esterno se ti servono anche le righe zero.

2

L'ORM di Django non renderà questo super-semplice. Il modo più semplice è quello di fare qualcosa di simile:

per la carriera in Career.objects.all():. career.dwarf_set.all() count()

che eseguirà 1 query per ogni posto di lavoro (O (n) complessità).

Si potrebbe provare ad accelerare utilizzando Django's Aggregation feature, ma non sono del tutto sicuro se farà quello che ti serve. Dovresti dare un'occhiata.

La terza opzione è l'utilizzo di SQL personalizzato, che assolverà assolutamente il lavoro. Devi solo scriverlo e gestirlo man mano che la tua app cresce e cambia ...

Problemi correlati