1
0
mirror of https://github.com/django/django.git synced 2024-12-27 03:25:58 +00:00
django/tests/regressiontests/null_queries/models.py
Malcolm Tredinnick 923f78f504 Improved table join handling for comparisons against NULL.
This fixes a broad class of bugs involving filters that look for missing
related models and fields. Most of them don't seem to have been reported
(the added tests cover the root cause). The exception is that this has
also fixed #9868.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9979 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-06 02:02:09 +00:00

83 lines
2.5 KiB
Python

from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
def __unicode__(self):
return u"Q: %s " % self.question
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
def __unicode__(self):
return u"Choice: %s in poll %s" % (self.choice, self.poll)
# A set of models with an inner one pointing to two outer ones.
class OuterA(models.Model):
pass
class OuterB(models.Model):
data = models.CharField(max_length=10)
class Inner(models.Model):
first = models.ForeignKey(OuterA)
second = models.ForeignKey(OuterB, null=True)
__test__ = {'API_TESTS':"""
# Regression test for the use of None as a query value. None is interpreted as
# an SQL NULL, but only in __exact queries.
# Set up some initial polls and choices
>>> p1 = Poll(question='Why?')
>>> p1.save()
>>> c1 = Choice(poll=p1, choice='Because.')
>>> c1.save()
>>> c2 = Choice(poll=p1, choice='Why Not?')
>>> c2.save()
# Exact query with value None returns nothing ("is NULL" in sql, but every 'id'
# field has a value).
>>> Choice.objects.filter(choice__exact=None)
[]
Excluding the previous result returns everything.
>>> Choice.objects.exclude(choice=None).order_by('id')
[<Choice: Choice: Because. in poll Q: Why? >, <Choice: Choice: Why Not? in poll Q: Why? >]
# Valid query, but fails because foo isn't a keyword
>>> Choice.objects.filter(foo__exact=None)
Traceback (most recent call last):
...
FieldError: Cannot resolve keyword 'foo' into field. Choices are: choice, id, poll
# Can't use None on anything other than __exact
>>> Choice.objects.filter(id__gt=None)
Traceback (most recent call last):
...
ValueError: Cannot use None as a query value
# Can't use None on anything other than __exact
>>> Choice.objects.filter(foo__gt=None)
Traceback (most recent call last):
...
ValueError: Cannot use None as a query value
# Related managers use __exact=None implicitly if the object hasn't been saved.
>>> p2 = Poll(question="How?")
>>> p2.choice_set.all()
[]
# Querying across reverse relations and then another relation should insert
# outer joins correctly so as not to exclude results.
>>> obj = OuterA.objects.create()
>>> OuterA.objects.filter(inner__second=None)
[<OuterA: OuterA object>]
>>> OuterA.objects.filter(inner__second__data=None)
[<OuterA: OuterA object>]
>>> _ = Inner.objects.create(first=obj)
>>> Inner.objects.filter(first__inner__second=None)
[<Inner: Inner object>]
"""}