Ticket #11670: 11670.diff
File 11670.diff, 5.4 KB (added by , 15 years ago) |
---|
-
django/db/models/sql/constants.py
diff --git a/django/db/models/sql/constants.py b/django/db/models/sql/constants.py index 63c704f..1a2cc72 100644
a b QUERY_TERMS = dict([(x, None) for x in ( 7 7 'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex', 8 8 )]) 9 9 10 # Valid query types for related fields. 11 # See `django.db.models.fields.related.RelatedField.get_db_prep_lookup`. 12 RELATED_QUERY_TERMS = dict([(x, None) for x in ( 13 'exact', 'gt', 'lt', 'gte', 'lte', 'range', 'in', 'isnull' 14 )]) 15 10 16 # Size of each "chunk" for get_iterator calls. 11 17 # Larger values are slightly faster at the expense of more storage space. 12 18 GET_ITERATOR_CHUNK_SIZE = 100 -
django/db/models/sql/query.py
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 9a19a9e..d9f357b 100644
a b class Query(object): 77 77 78 78 alias_prefix = 'T' 79 79 query_terms = QUERY_TERMS 80 related_query_terms = RELATED_QUERY_TERMS 80 81 aggregates_module = base_aggregates_module 81 82 82 83 compiler = 'SQLCompiler' … … class Query(object): 953 954 raise FieldError("Cannot parse keyword query %r" % arg) 954 955 955 956 # Work out the lookup type and remove it from 'parts', if necessary. 956 if len(parts) == 1 or parts[-1] not in self.query_terms:957 if len(parts) == 1: 957 958 lookup_type = 'exact' 958 959 else: 959 lookup_type = parts.pop() 960 # Find the last field in the lookup and determine if it's a 961 # related field. By restricting the query terms used for lookups 962 # that span relations, we prevent valid field names like "year" 963 # from being misinterpreted as lookup types. 964 try: 965 lookup_model = self.model 966 for field_name in parts[:-1]: 967 lookup_field = lookup_model._meta.get_field(field_name) 968 if lookup_field.rel: 969 lookup_model = lookup_field.rel.to 970 except FieldDoesNotExist: 971 query_terms = self.query_terms 972 else: 973 if lookup_field.rel: 974 query_terms = self.related_query_terms 975 else: 976 query_terms = self.query_terms 977 if parts[-1] in query_terms: 978 lookup_type = parts.pop() 979 else: 980 lookup_type = 'exact' 960 981 961 982 # By default, this is a WHERE clause. If an aggregate is referenced 962 983 # in the value, the filter will be promoted to a HAVING -
new file tests/regressiontests/model_related_lookups_regress/models.py
diff --git a/tests/regressiontests/model_related_lookups_regress/__init__.py b/tests/regressiontests/model_related_lookups_regress/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/regressiontests/model_related_lookups_regress/models.py b/tests/regressiontests/model_related_lookups_regress/models.py new file mode 100644 index 0000000..97d12cf
- + 1 from django.db import models 2 3 4 class Season(models.Model): 5 year = models.PositiveSmallIntegerField() 6 world_series_winner = models.CharField(max_length=100) 7 8 def __unicode__(self): 9 return unicode(self.year) 10 11 12 class Game(models.Model): 13 season = models.ForeignKey(Season, related_name='games') 14 home = models.CharField(max_length=100) 15 away = models.CharField(max_length=100) 16 17 def __unicode__(self): 18 return u"%s at %s" % (self.away, self.home) 19 20 21 class Player(models.Model): 22 name = models.CharField(max_length=100) 23 games = models.ManyToManyField(Game, related_name='players') 24 25 def __unicode__(self): 26 return self.name 27 28 29 __test__ = {'API_TESTS':""" 30 Regression test for #11670 31 32 >>> season_2009 = Season.objects.create(year=2009, world_series_winner="New York Yankees") 33 >>> cardinals_at_astros = season_2009.games.create(home="Houston Astros", away="St. Louis Cardinals") 34 35 >>> season_2010 = Season.objects.create(year=2010, world_series_winner="Houston Astros") 36 >>> cubs_at_astros = season_2010.games.create(home="Houston Astros", away="Chicago Cubs") 37 >>> brewers_at_astros = season_2010.games.create(home="Houston Astros", away="Milwaukee Brewers") 38 39 >>> Game.objects.count() 40 3 41 42 >>> Game.objects.filter(season__year=2010).count() 43 2 44 45 >>> Game.objects.get(season__year=2009) 46 <Game: St. Louis Cardinals at Houston Astros> 47 48 >>> hunter_pence = Player.objects.create(name="Hunter Pence") 49 >>> hunter_pence.games = Game.objects.filter(season__year__in=[2009, 2010]) 50 51 >>> hunter_pence.games.count() 52 3 53 54 >>> hunter_pence.games.filter(season__year=2009).count() 55 1 56 57 >>> hunter_pence.games.filter(season__year__exact=2010).count() 58 2 59 60 >>> pudge = Player.objects.create(name="Ivan Rodriquez") 61 >>> pudge.games = Game.objects.filter(season__year=2009) 62 63 >>> pedro_feliz = Player.objects.create(name="Pedro Feliz") 64 >>> pedro_feliz.games = Game.objects.filter(season__year=2010) 65 66 >>> Player.objects.count() 67 3 68 69 >>> Player.objects.filter(games__season__year=2009).distinct().count() 70 2 71 72 >>> Player.objects.filter(games__season__year__exact=2010).distinct().count() 73 2 74 75 >>> Player.objects.filter(games__season__world_series_winner__icontains="Yankees").distinct().count() 76 2 77 78 >>> Player.objects.filter(games__season__world_series_winner__iexact="Houston Astros").distinct().count() 79 2 80 81 """}