I have a fairly complex query that I’ve been trying to create using Django’s query abstraction language, but so far no luck.
I have 2 tables I need to query one of which is auth_user. The other table I’ll call contact. The contact table has two columns each of which are foreign keys to the auth_user table (user_id, user_accept_id). The contact table establishes relationships between people on the website.
What I need to build is a query that retrieves people I am NOT connected to.
Here is the equivalent query in raw sql, my id will be 1 for the sake of the query below.
select u.id, u.username, resultset.id, resultset.myid, resultset.cid
from auth_user as u
left join (
select id, user_id as myid, user_accept_id as cid from polls_contacts where user_id=1
union
select id, user_accept_id as myid, user_id as cid from polls_contacts where user_accept_id=1
group by myid, cid
) as resultset on u.id=resultset.cid
where
u.id != 1 and resultset.id IS NULL;
I’m considering just using the method to write this query as raw, but would rather find out how to use the abstraction layer, if possible.
In [1]: user_id = 1
...: contact_users = Contact.objects.filter(user_id=user_id).values_list('user_accept_id')
...: accepted_users = Contact.objects.filter(user_accept_id=user_id).values_list('user_id')
...: unconnected_users = User.objects.exclude(id__in=contact_users.union(accepted_users)).exclude(id=user_id)
In [2]: str(unconnected_users.query)
Out[2]: 'SELECT "core_user"."id" FROM "core_user" WHERE (NOT ("core_user"."id" IN (SELECT "core_contact"."user_accept_id" FROM "core_contact" WHERE "core_contact"."user_id" = 1 UNION SELECT "core_contact"."user_id" FROM "core_contact" WHERE "core_contact"."user_accept_id" = 1)) AND NOT ("core_user"."id" = 1))'
It seesm your Contacts tabel is working as a many-to-many relationship - are you not using a ManyToManyField?
Thanks Adam your query did indeed work. So the query you provided me looked at the system set of users, and displays those systems users which do not already belong to me.
However, now I need to get the users that belong to me (I’ve used the same union statement for this) and exclude a subset of users in the system that belong to a ‘project’.
So the website logic is first connect with my group of contacts. Now out of this group of contacts I can add them to projects.
My steps are:
1 - get the users belonging to the project
2 - use the same union logic to get my contacts
3 - exclude the project users from the group of my contacts, so that I have a nice clean list of users that I might want to add to the project
However, it seems that django does not let filter/exclude happen on union’d queries. Any ideas on how I can achieve this subset of my contacts that do NOT belong to a given project?
Here are the queries i tried and the error I received:
user_id=1
project_id=1