mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #11670 -- Prevented genuine model fields named 'year', 'month', 'gt', 'lt' etc. from being mistaken for lookup types in lookups across relations. Thanks to andy for the report, to jpwatts for the initial patch and to Anssi Kääriäinen and Alex Gaynor for the reviews.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17450 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
@@ -27,3 +27,25 @@ class Tag(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
|
||||
class Season(models.Model):
|
||||
year = models.PositiveSmallIntegerField()
|
||||
gt = models.IntegerField(null=True, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.year)
|
||||
|
||||
class Game(models.Model):
|
||||
season = models.ForeignKey(Season, related_name='games')
|
||||
home = models.CharField(max_length=100)
|
||||
away = models.CharField(max_length=100)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s at %s" % (self.away, self.home)
|
||||
|
||||
class Player(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
games = models.ManyToManyField(Game, related_name='players')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
@@ -1,4 +1,4 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import absolute_import, with_statement
|
||||
|
||||
from datetime import datetime
|
||||
from operator import attrgetter
|
||||
@@ -6,12 +6,11 @@ from operator import attrgetter
|
||||
from django.core.exceptions import FieldError
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
|
||||
from .models import Author, Article, Tag
|
||||
from .models import Author, Article, Tag, Game, Season, Player
|
||||
|
||||
|
||||
class LookupTests(TestCase):
|
||||
|
||||
#def setUp(self):
|
||||
def setUp(self):
|
||||
# Create a few Authors.
|
||||
self.au1 = Author(name='Author 1')
|
||||
@@ -610,3 +609,80 @@ class LookupTests(TestCase):
|
||||
a16.save()
|
||||
self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'b(.).*b\1'),
|
||||
['<Article: barfoobaz>', '<Article: bazbaRFOO>', '<Article: foobarbaz>'])
|
||||
|
||||
def test_nonfield_lookups(self):
|
||||
"""
|
||||
Ensure that a lookup query containing non-fields raises the proper
|
||||
exception.
|
||||
"""
|
||||
with self.assertRaises(FieldError):
|
||||
Article.objects.filter(headline__blahblah=99)
|
||||
with self.assertRaises(FieldError):
|
||||
Article.objects.filter(headline__blahblah__exact=99)
|
||||
with self.assertRaises(FieldError):
|
||||
Article.objects.filter(blahblah=99)
|
||||
|
||||
def test_lookup_collision(self):
|
||||
"""
|
||||
Ensure that genuine field names don't collide with built-in lookup
|
||||
types ('year', 'gt', 'range', 'in' etc.).
|
||||
Refs #11670.
|
||||
"""
|
||||
|
||||
# Here we're using 'gt' as a code number for the year, e.g. 111=>2009.
|
||||
season_2009 = Season.objects.create(year=2009, gt=111)
|
||||
season_2009.games.create(home="Houston Astros", away="St. Louis Cardinals")
|
||||
season_2010 = Season.objects.create(year=2010, gt=222)
|
||||
season_2010.games.create(home="Houston Astros", away="Chicago Cubs")
|
||||
season_2010.games.create(home="Houston Astros", away="Milwaukee Brewers")
|
||||
season_2010.games.create(home="Houston Astros", away="St. Louis Cardinals")
|
||||
season_2011 = Season.objects.create(year=2011, gt=333)
|
||||
season_2011.games.create(home="Houston Astros", away="St. Louis Cardinals")
|
||||
season_2011.games.create(home="Houston Astros", away="Milwaukee Brewers")
|
||||
hunter_pence = Player.objects.create(name="Hunter Pence")
|
||||
hunter_pence.games = Game.objects.filter(season__year__in=[2009, 2010])
|
||||
pudge = Player.objects.create(name="Ivan Rodriquez")
|
||||
pudge.games = Game.objects.filter(season__year=2009)
|
||||
pedro_feliz = Player.objects.create(name="Pedro Feliz")
|
||||
pedro_feliz.games = Game.objects.filter(season__year__in=[2011])
|
||||
johnson = Player.objects.create(name="Johnson")
|
||||
johnson.games = Game.objects.filter(season__year__in=[2011])
|
||||
|
||||
# Games in 2010
|
||||
self.assertEqual(Game.objects.filter(season__year=2010).count(), 3)
|
||||
self.assertEqual(Game.objects.filter(season__year__exact=2010).count(), 3)
|
||||
self.assertEqual(Game.objects.filter(season__gt=222).count(), 3)
|
||||
self.assertEqual(Game.objects.filter(season__gt__exact=222).count(), 3)
|
||||
|
||||
# Games in 2011
|
||||
self.assertEqual(Game.objects.filter(season__year=2011).count(), 2)
|
||||
self.assertEqual(Game.objects.filter(season__year__exact=2011).count(), 2)
|
||||
self.assertEqual(Game.objects.filter(season__gt=333).count(), 2)
|
||||
self.assertEqual(Game.objects.filter(season__gt__exact=333).count(), 2)
|
||||
self.assertEqual(Game.objects.filter(season__year__gt=2010).count(), 2)
|
||||
self.assertEqual(Game.objects.filter(season__gt__gt=222).count(), 2)
|
||||
|
||||
# Games played in 2010 and 2011
|
||||
self.assertEqual(Game.objects.filter(season__year__in=[2010, 2011]).count(), 5)
|
||||
self.assertEqual(Game.objects.filter(season__year__gt=2009).count(), 5)
|
||||
self.assertEqual(Game.objects.filter(season__gt__in=[222, 333]).count(), 5)
|
||||
self.assertEqual(Game.objects.filter(season__gt__gt=111).count(), 5)
|
||||
|
||||
# Players who played in 2009
|
||||
self.assertEqual(Player.objects.filter(games__season__year=2009).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__year__exact=2009).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt=111).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt__exact=111).distinct().count(), 2)
|
||||
|
||||
# Players who played in 2010
|
||||
self.assertEqual(Player.objects.filter(games__season__year=2010).distinct().count(), 1)
|
||||
self.assertEqual(Player.objects.filter(games__season__year__exact=2010).distinct().count(), 1)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt=222).distinct().count(), 1)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt__exact=222).distinct().count(), 1)
|
||||
|
||||
# Players who played in 2011
|
||||
self.assertEqual(Player.objects.filter(games__season__year=2011).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__year__exact=2011).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt=333).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__year__gt=2010).distinct().count(), 2)
|
||||
self.assertEqual(Player.objects.filter(games__season__gt__gt=222).distinct().count(), 2)
|
||||
|
||||
Reference in New Issue
Block a user