On Wed, Dec 4, 2013 at 10:24 AM, Aamu Padi <aamup...@gmail.com> wrote: > How do I check whether there is a thread containing only the sender (user 1) > and the recipient (user 2), and no other users. > > models.py > > class Thread(models.Model): > user = models.ManyToManyField(User) > is_hidden = models.ManyToManyField(User, > related_name='hidden_thread', blank=True) > > class Message(models.Model): > thread = models.ForeignKey(Thread) > sent_date = models.DateTimeField(default=datetime.now) > sender = models.ForeignKey(User) > body = models.TextField() > is_hidden = models.ManyToManyField(User, > related_name='hidden_message', blank=True) > > I tried > > >>> Thread.objects.filter(user=user1&user2) > >>> Thread.objects.filter(user=user1|user2) > # Both gave me an error: Unsupported operand. > > # Then this > >>> Thread.objects.filter(Q(user=user1) & Q(user=user2)) > # Which gave me no threads at all. > > # Then this > >>> Thread.objects.filter(Q(user=user1) | Q(user=user2)).distinct() > # Gave me threads of both the users. > > What I want is to check the thread, with the specified users only. Suppose, > User 1 wants to send a message to User 2. What I want is, first check > whether there is a thread between both the users. If there is, get that > thread, or else create a new one. How is it possible? What is the best way > to do it. Please help me. Thank you.
I hope you understand SQL a little, as it will be required to follow this explanation. The condition "Thread.objects.filter(user=..)" goes across a join to the users<->threads "through" table, which has columns (id, thread_id, user_id). When you specify conditions in a "filter()" call, each of the conditions specified in that call is AND'ed together (the equivalent of what you were doing in the "Q(user=user1) & Q(user=user2)", django would do that for you). However, what does that mean, in terms of SQL? Well, it means "find me rows from the users<->threads through table that have user_id=user1.pk and user_id=user2.pk". Obviously, this will never find results unless user1==user2. So, you need to specify that you want to join twice to that table. You do this by specifying the conditions for each join in a separate "filter()" call, and so to find threads that have a row with user1 in the through table, and also have user2 in the through table: Thread.objects.filter(user=user1).filter(user=user2) You started by asking how to find threads which had user1 and user2, but no other users. This is more complex, you need to count the number of users in the thread without filtering the users first! This means two queries, or a sub query: threads_with_both = Thread.objects.filter(user=user1).filter(user=user2) threads_with_only_both = Thread.objects.filter( pk__in=threads_with_both).annotate( num_users=Count('user')).filter( num_users=2) > > And please tell me what's the difference between | and &? Because I had very > different results with these two. | is OR & is AND So to find threads with either user1 or user2 (or both): Thread.objects.filter(Q(user=user1) | Q(user=user2)) To find hidden threads with user1 Thread.objects.filter(Q(user=user1) & Q(is_hidden=True)) which is the same as Thread.objects.filter(user=user1, is_hidden=True) Cheers Tom -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at http://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAFHbX1J%3DWX9p12B2X%2B1b_afDF0yEr80t0cfBsGbggzrKEBqqTg%40mail.gmail.com. For more options, visit https://groups.google.com/groups/opt_out.