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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---