On 9/3/06, kdart <[EMAIL PROTECTED]> wrote:
It's not a bug - it's a slight misunderstanding on your part on how filtering works.
The problem is that ultimately, Django is doing what it does by retreiving rows from a database. By mentioning an m2m relation in your query, Django is stimulated to perform a join with another table, creating 'super-rows' that are the composition of the model you are querying and the model that is m2m related. Then, based on the criteria you provide, rows are filtered out. So, as a result of asking about the 'classifications' related to 'queryterms', you will end up with super-rows that look like:
queryterm 1, classification 4
queryterm 1, classification 6
queryterm 2, classification 3
queryterm 3, classification 4
If you filter for 'classification=4', you will get 2 rows; if you ask for 'classification=6' you get 1 row. But if you ask for 'classification=6 AND classification=4', you get nothing, because no _single_ row can contain _both_ classifications.
The correct way to compose your query would be to do the AND on the query set, rather than in the filter;
QueryTerm.objects.filter(classification=4) & QueryTerm.objects.filter(classification=6)
This gets two distinct sets of objects, and then determines the elements that exist in both sets (in this case, just queryterm 1). Unfortunately, the QuerySet intersection/union operations are the subject of a known bug (ticket #1801), so while the syntax exists, this might not actually work in your case.
So, other ways to solve the problem:
1) Get the two QuerySets and perform the intersection yourself using Python intersection operators. This requires two SQL operations and doesn't exploit the capabilities of having your data in a relational database, so the code will not be as efficient.
2) Roll your own SQL; what you want can be achieved if you perform 2 joins with the classification m2m table (rather than the single join that Django uses) and add the right WHERE clauses. This isn't as pretty, but should be faster at runtime.
You _might_ be able to acheive option 2 without dropping to raw SQL if you write a custom Q object to force a second join; however, this approach is not for beginners. Search the archives of this mailing list for others that have attempted this approach (there have been a couple in the last 2 months) and start spelunking through django/db/models/query.py if you feel enthused.
Yours,
Russ Magee %-)
But if I AND them (here is the problem/question), nothing...
...
So, is this a bug? Or am I doing something wrong?
It's not a bug - it's a slight misunderstanding on your part on how filtering works.
The problem is that ultimately, Django is doing what it does by retreiving rows from a database. By mentioning an m2m relation in your query, Django is stimulated to perform a join with another table, creating 'super-rows' that are the composition of the model you are querying and the model that is m2m related. Then, based on the criteria you provide, rows are filtered out. So, as a result of asking about the 'classifications' related to 'queryterms', you will end up with super-rows that look like:
queryterm 1, classification 4
queryterm 1, classification 6
queryterm 2, classification 3
queryterm 3, classification 4
If you filter for 'classification=4', you will get 2 rows; if you ask for 'classification=6' you get 1 row. But if you ask for 'classification=6 AND classification=4', you get nothing, because no _single_ row can contain _both_ classifications.
The correct way to compose your query would be to do the AND on the query set, rather than in the filter;
QueryTerm.objects.filter(classification=4) & QueryTerm.objects.filter(classification=6)
This gets two distinct sets of objects, and then determines the elements that exist in both sets (in this case, just queryterm 1). Unfortunately, the QuerySet intersection/union operations are the subject of a known bug (ticket #1801), so while the syntax exists, this might not actually work in your case.
So, other ways to solve the problem:
1) Get the two QuerySets and perform the intersection yourself using Python intersection operators. This requires two SQL operations and doesn't exploit the capabilities of having your data in a relational database, so the code will not be as efficient.
2) Roll your own SQL; what you want can be achieved if you perform 2 joins with the classification m2m table (rather than the single join that Django uses) and add the right WHERE clauses. This isn't as pretty, but should be faster at runtime.
You _might_ be able to acheive option 2 without dropping to raw SQL if you write a custom Q object to force a second join; however, this approach is not for beginners. Search the archives of this mailing list for others that have attempted this approach (there have been a couple in the last 2 months) and start spelunking through django/db/models/query.py if you feel enthused.
Yours,
Russ Magee %-)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/django-users
-~----------~----~----~----~------~----~------~--~---