2013-05-16 14 views
7

Sto usando annotate per aggiungere una proprietà a un oggetto che posso quindi utilizzare per order_by. Tuttavia, voglio annotare su un campo di una relazione su una relazione. So che dovrei essere in grado di raggiungere il campo in qualche modo usando la notazione con doppio trattino, ma non riesco a capirlo.Django: come ordinare su un campo correlato di un campo correlato

Qui ci sono i modelli:

class Group(Taggable, Uploadable): 
    name   = models.CharField(max_length=250, db_index=True) 
    description  = models.TextField(max_length=5000, null=True, 
         blank=True, db_index=True) 
    private   = models.BooleanField(default=False) 
    members   = models.ManyToManyField(User, null=True, 
         related_name='members', through='GroupToUser') 
    pending_members = models.ManyToManyField(User, null=True, 
         related_name='pending_members') 
    admin   = models.ForeignKey(User, null=True) 
    timestamp  = models.DateTimeField(auto_now_add=True) 
    author   = models.ForeignKey(User, related_name='author') 

class Discussion(Taggable, Uploadable): 
    author  = models.ForeignKey(User) 
    title  = models.CharField(max_length=250, db_index=True) 
    description = models.TextField(max_length=5000, null=True, 
        blank=True, db_index=True) 
    group  = models.ForeignKey(Group, null=True) 
    timestamp = models.DateTimeField(auto_now_add=True) 

class DiscussionResponse(Uploadable): 
    author  = models.ForeignKey(User) 
    discussion = models.ForeignKey(Discussion) 
    message = models.TextField(max_length=5000) 
    timestamp = models.DateTimeField(auto_now_add=True) 

Quindi, una discussione può opzionalmente essere associato ad un gruppo, e DiscussionResponses sono associati a una discussione. Quello che mi piacerebbe fare è trovare la DiscussionResponse più recente su qualsiasi discussione connessa a un gruppo, se esiste, e ordinare in base a ciò.

ho ottenuto fino a questo:

Group.objects.filter(some_filtering).distinct().annotate(
    last_response=Max('some__reverse__relationship__timestamp').order_by(
     '-last_response') 

io proprio non riesco a capire il modo giusto per ottenere il timestamp su un DiscussionResponse in questo caso.

AGGIORNAMENTO: Si può effettivamente ordinare con un valore annotato. Ecco un esempio con una order_by sul timestamp di una discussione relativa:

>>> groups = Group.objects.all().annotate(
     last_response=Max('discussion__timestamp')).order_by('-last_response') 
>>> for group in groups: 
...  print(group.id, group.last_response) 
...  
... 
(2L, datetime.datetime(2013, 5, 8, 15, 32, 31)) 
(1L, None) 
(3L, None) 
(4L, None) 
(6L, None) 
(7L, None) 
(8L, None) 
(9L, None) 

In questo caso, solo il gruppo # 2 è correlata discussioni perciò è stato spostato verso l'alto; il resto mantiene l'ordine naturale. Quello che mi piacerebbe davvero fare, però, è spostare i gruppi che hanno le recenti risposte alle conversazioni spostate all'inizio dell'elenco. Ecco perché ho pensato che il 'discussion__discussionresponse__timestamp' avrebbe funzionato, ma non sembra.

+0

Ho provato quanto segue, nessuno dei quali ha lavorato: 'discussion__discussionresponse__timestamp',' discussion_set__discussionresponse__timestamp', e 'discussion set__discussionresponse__timestamp' – foresmac

+0

Non capisco cosa cerchi di realizzare. Ad esempio, dichiari 'last_response = Max (...)' che ti darà un timestamp, e quindi ordini questo valore, devi ordinare per colonna, non un valore, ho ragione? Quello che vuoi è l'ordine per timestamp colum ?? –

+0

Si può 'order_by' su un valore annotato; Ho usato il trucco prima. Il problema è che non riesco a ottenere il timestamp dei DiscussionResponses relativi alle discussioni relative a un gruppo. – foresmac

risposta

1

Ok, apparentemente è solo 'discussion__discussionresponse__timestamp'. Ho provato nel guscio Django e non ha funzionato dopo il salvataggio di una nuova DiscussionResponse, ma ha funzionato parecchi minuti più tardi, quando ho provato di nuovo:

>>> groups = Group.objects.all().annotate(last_response=Max(
     'discussion__discussionresponse__timestamp')).order_by('-last_response') 
>>> for group in groups: 
...  print(group.id, group.last_response) 
...  
... 
(2L, datetime.datetime(2013, 5, 16, 14, 56, 22)) 
(1L, None) 
(3L, None) 
(4L, None) 
(6L, None) 
(7L, None) 
(8L, None) 
(9L, None) 
>>> 

Se qualcuno sa il motivo per cui non ha funzionato a destra dopo il salvataggio un nuovo oggetto nel database, ma ha funzionato in un secondo momento, sarebbe probabilmente un'informazione utile.

Ecco un altro run a query con discussioni/risposte aggiunti a un altro gruppo solo per la verifica aggiunto:

>>> groups = Group.objects.all().annotate(last_response=Max('discussion__discussionresponse__timestamp')).order_by('-last_response') 
>>> for group in groups: 
...  print(group.id, group.last_response) 
...  
... 
(4L, datetime.datetime(2013, 5, 16, 15, 25, 40)) 
(2L, datetime.datetime(2013, 5, 16, 15, 16, 46)) 
(1L, None) 
(3L, None) 
(6L, None) 
(7L, None) 
(8L, None) 
(9L, None) 
>>> 
+0

Sentitevi liberi di contrassegnare come risposta. – stellarchariot