I am trying to figure out how to do isnull lookups with the admin change list filter. I am using the django master branch (off of github), updated to 4/28.
I have a couple models with a simple relation: from django.db import models class ModelOne(models.Model): pass class ModelTwo(models.Model): one = models.ForeignKey(ModelOne) I can filter on `two_set__isnull=True` to find ModelOne not referenced by any ModelTwo and `two_set__isnull=False` to find ModelOne that is referenced by any ModelTwo. That works well enough in python. I can't find a way to do this with the admin change list filter. The ChangeList class does recognize and accept querystrings like the following: /admin/foo/modelone/?two_set__isnull=True /admin/foo/modelone/?two_set__isnull= /admin/foo/modelone/?two_set__isnull The problem is that the parameters are all strings. It seems the behavior of isnull lookups is not useful for non boolean values. Perhaps that is sensible. I have a couple ideas toward making this work. One idea involves the ChangeList class that does the work of converting the request.GET parameters to a QuerySet. This could do the conversion to a boolean value. There is presently a branch to specially handle in lookups there. My other idea is to make isnull lookups work for non-boolean types. This is actually already done to generate the IS NULL / IS NOT NULL sql, but there is also a test to change the join type so NULL values or returned for rows where the join fails (instead of no row). Is this an issue for anyone else? Am I barking up the wrong tree? I'm fairly new to django, so I could just be missing something here. Kai Patch to make the admin ChangeList class coerce isnull lookups to use bool. --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -185,6 +185,10 @@ class ChangeList(object): if key.endswith('__in'): lookup_params[key] = value.split(',') + # if key ends with __isnull, convert the value to a boolean + elif key.endswith('__isnull'): + lookup_params[key] = bool(value) + # Apply lookup parameters from the query string. try: qs = qs.filter(**lookup_params) Patch to make BaseQuery use a more relaxed test for truthiness. --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1536,7 +1536,7 @@ class BaseQuery(object): can_reuse) return - if (lookup_type == 'isnull' and value is True and not negate and + if (lookup_type == 'isnull' and value and not negate and len(join_list) > 1): # If the comparison is against NULL, we may need to use some left # outer joins when creating the join chain. This is only done when --~--~---------~--~----~------------~-------~--~----~ 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 django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---