2017-07-26 3 views
0

Je ces modèles (très simplifié)Django - distinct() ne fonctionne pas avec annoter()

class Offer(models.Model): 
    product = ForeignKey(Product) 

class Conversation(models.Model): 
    user = ForeignKey(settings.AUTH_USER_MODEL) 
    receiver = ForeignKey(settings.AUTH_USER_MODEL) 
    offer = ForeignKey(Offer, related_name='conversations') 
    last_message = OneToOneField('Message', null=True, blank=True) 

class Message(models.Model): 
    message = TextField() 

    status = CharField(
     max_length=128, 
     choices=constants.MESSAGE_STATUS_CHOICES, 
     default=constants.MESSAGE_STATUS_SENT, 
    ) 
    sender = ForeignKey(settings.AUTH_USER_MODEL) 
    conversation = ForeignKey(Conversation) 

    created_at = DateTimeField(auto_now_add=True) 

Je veux proposer des offres avec des conversations, commandés par des messages non vus d'abord, donc je pensais que je d utiliser les annotations pour indiquer si l'offre est considérée ou non, mais distincte() ne fonctionne pas avec annoter():

class User(AbstractUser): 
    def get_offers_with_conversations(self): 
     """ 
     Get offers with conversations. Not seen conversations first.' 
     """ 

     return Offer.objects.filter(
      Q(conversations__user=self) | 
      Q(conversations__receiver=self), 
     ).annotate(seen_conversations=Case(
      When(
       ~Q(conversations__last_message__sender=self) & 
       Q(conversations__last_message__status=conversation_constants.MESSAGE_STATUS_SENT), 

       then=Value(True) 
      ), 
      default=Value(False), output_field=BooleanField() 
     )).order_by(
      '-seen_conversations', '-conversations__last_message__created_at' 
     ).distinct() 

Toute aide sera la bienvenue. Je vous remercie.

+0

peux vous montrer exemple de données brutes , données après une requête d'annotation avec des commentaires sur les lignes supplémentaires? –

Répondre

0

pour distinctes vous avez besoin d'ajouter des valeurs, par exemple:

return Offer.objects.filter(
     Q(conversations__user=self) | 
     Q(conversations__receiver=self), 
    ).annotate(seen_conversations=Case(
     When(
      ~Q(conversations__last_message__sender=self) & 
      Q(conversations__last_message__status=conversation_constants.MESSAGE_STATUS_SENT), 

      then=Value(True) 
     ), 
     default=Value(False), output_field=BooleanField() 
    )).values(
    'seen_conversations', 'conversations__last_message__created_at' 
    ).order_by(
     '-seen_conversations', '-conversations__last_message__created_at' 
    ).distinct() 
+0

Merci, mais cela ne fonctionne pas. – nickname123

0

Je ne suis pas sûr, mais peut-être se joindre à filtre à crochets et

Offer.objects.filter( Q( Q(conversations__user=self) | Q(conversations__receiver=self) ), ).