Note: This was working under Django 1.11.7.
{{{
# models.py
from django.contrib.gis.db import models
class Restaurant(models.Model):
location = models.PointField(blank=True, null=True, db_index=True)
}}}
{{{
# tests.py
from django.test import TestCase
from restaurants.models import Restaurant
class RestaurantTestCase(TestCase):
def test_no_location(self):
# Failing query
Restaurant.objects.filter(location=None)
}}}
{{{
$ python manage.py testCreating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_no_location (restaurants.tests.RestaurantTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/wli/projects/point-field-bug/restaurants/tests.py", line 7,
in test_no_location
Restaurant.objects.filter(location=None)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/query.py", line 836, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/query.py", line 854, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/sql/query.py", line 1252, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/sql/query.py", line 1276, in _add_q
split_subq=split_subq,
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/sql/query.py", line 1214, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/sql/query.py", line 1084, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/contrib/gis/db/models/lookups.py", line 23, in __init__
super().__init__(lhs, rhs)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/lookups.py", line 18, in __init__
self.rhs = self.get_prep_lookup()
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/db/models/lookups.py", line 68, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/home/wli/.envs/point-field-bug/lib/python3.6/site-
packages/django/contrib/gis/db/models/fields.py", line 188, in
get_prep_value
raise ValueError('Cannot use object with type %s for a spatial lookup
parameter.' % type(obj).__name__)
ValueError: Cannot use object with type NoneType for a spatial lookup
parameter.
----------------------------------------------------------------------
Ran 1 test in 0.005s
FAILED (errors=1)
Destroying test database for alias 'default'...
}}}
Workaround:
{{{
Restaurant.objects.extra(where=['location IS NULL'])
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28896>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by William Li):
This is a suspicious commit, but I'm not well-versed enough in the query
internals to know for sure:
https://github.com/django/django/commit/3b56f2191df0a437740182d49efe3be16c4d0d58
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:1>
* keywords: QuerySet.extra PointField GeoDjango => PointField GeoDjango
* cc: Sergey Fedoseev (added)
* component: Database layer (models, ORM) => GIS
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted
Comment:
Bisected to 58da81a5a372a69f0bac801c412b57f3cce5f188. I would imagine that
`__isnull=True` works, but we should either restore the old behavior of
accepting `None` or document the backwards incompatibility.
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:2>
* status: new => assigned
* owner: nobody => Sergey Fedoseev
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:3>
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/9435 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:4>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:5>
Comment (by Tim Graham <timograham@…>):
In [changeset:"10bfa876be59feec24bb6a40fa11bece808ee405" 10bfa876]:
{{{
#!CommitTicketReference repository=""
revision="10bfa876be59feec24bb6a40fa11bece808ee405"
Refs #27985 -- Reallowed using __exact=None as an alias for __isnull=True
if a custom lookup class with lookup_name != None is registered as the
exact lookup.
Regression in 58da81a5a372a69f0bac801c412b57f3cce5f188 and prerequisite
for refs #28896.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:6>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"da71e4bb086593b5ca76bf698358d27ead2cfed2" da71e4bb]:
{{{
#!CommitTicketReference repository=""
revision="da71e4bb086593b5ca76bf698358d27ead2cfed2"
Fixed #28896 -- Reallowed filtering a queryset with GeometryField=None.
Regression in 58da81a5a372a69f0bac801c412b57f3cce5f188.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:7>
Comment (by Tim Graham <timograham@…>):
In [changeset:"ce26ec01631b00f1d0062a18c79abc93c489b75d" ce26ec0]:
{{{
#!CommitTicketReference repository=""
revision="ce26ec01631b00f1d0062a18c79abc93c489b75d"
[2.0.x] Fixed #28896 -- Reallowed filtering a queryset with
GeometryField=None.
Regression in 58da81a5a372a69f0bac801c412b57f3cce5f188.
Backport of da71e4bb086593b5ca76bf698358d27ead2cfed2 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:9>
Comment (by Tim Graham <timograham@…>):
In [changeset:"a5c60404476124c682c996bfb1eb077d59f1ec53" a5c6040]:
{{{
#!CommitTicketReference repository=""
revision="a5c60404476124c682c996bfb1eb077d59f1ec53"
[2.0.x] Refs #27985 -- Reallowed using __exact=None as an alias for
__isnull=True if a custom lookup class with lookup_name != None is
registered as the exact lookup.
Regression in 58da81a5a372a69f0bac801c412b57f3cce5f188 and prerequisite
for refs #28896.
Backport of 10bfa876be59feec24bb6a40fa11bece808ee405 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28896#comment:8>