Has the matter been completely put away?

I would like to bring it up again.

I have Articles and Categories. An Article belongs to Categories:

class Category(model):
  pass
class Article(model):
  category = ManyToManyField(Category)
  status = CharField(max_length=10)

Now I want all categories with articles that have status different than 
"archived".

I cannot do this with django's ORM!

Category.objects.filter(~Q(article_status="archived"))

will result in a query like this (simplified for readibility):
SELECT * FROM
category LEFT OUTER JOIN articlecategory ON category.id = 
articlecategory.category_id
WHERE NOT 
"category"."id" IN (
  SELECT U1."category_id" 
  FROM "articlecategory" U1 INNER JOIN "article" U2 ON (U1."article_id" = 
U2."id") 
  WHERE 
  (
      U2."status" = 'Archived'
      AND U1."category_id" IS NOT NULL
   )
) 

The key problem here is that the ~Q() part negates whole big part of SQL 
query, and instead of getting all categories with at least one not archived 
article, I get all categories that have no archived articles! You must 
agree, that it is not very unlikely that someone wants to query for sth 
like this. I cannot use Q(__lt)|Q(__gt) becouse this is not integer. If 
status was enumerated, I could select all values that are different than 
"archived". But in this case I cannot do anything (except custom sql which 
seems like overkill to such simple need).

Adding not equal operator (say __ne) would allow to do this really simply: 
Category.objects.filter(article_status__ne="archived")

potentially resulting with query like this:
SELECT * FROM
category LEFT OUTER JOIN articlecategory ON category.id = 
articlecategory.category_id
WHERE
"category"."id" IN (
  SELECT U1."category_id" 
  FROM "articlecategory" U1 INNER JOIN "article" U2 ON (U1."article_id" = 
U2."id") 
  WHERE 
  (
      U2."status" != 'Archived'
      AND U1."category_id" IS NOT NULL
   )
) 

My question is why deny user such obvious usage of ORM?

And btw, "not_in" would be really usefull too, argument the same, but I 
want to exclude three statuses ("archived", "deleted" and "draft").

-- 
Marek Brzóska

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/CE4o-iujriQJ.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to