[1.8.x] Fixed #23940 -- Allowed model fields to be named `exact`.

An explicit `__exact` lookup in the related managers filters
was interpreted as a reference to a foreign `exact` field.

Thanks to Trac alias zhiyajun11 for the report, Josh for the investigation,
Loïc for the test name and Tim for the review.

Backport of eb4cdfbdd6 from master
This commit is contained in:
Simon Charette 2015-01-22 01:43:49 -05:00
parent 7b92acea70
commit a301061f88
3 changed files with 12 additions and 3 deletions

View File

@ -681,7 +681,7 @@ def create_foreign_related_manager(superclass, rel_field, rel_model):
def __init__(self, instance): def __init__(self, instance):
super(RelatedManager, self).__init__() super(RelatedManager, self).__init__()
self.instance = instance self.instance = instance
self.core_filters = {'%s__exact' % rel_field.name: instance} self.core_filters = {rel_field.name: instance}
self.model = rel_model self.model = rel_model
def __call__(self, **kwargs): def __call__(self, **kwargs):

View File

@ -129,6 +129,7 @@ class Child7(Parent):
@python_2_unicode_compatible @python_2_unicode_compatible
class RelatedModel(models.Model): class RelatedModel(models.Model):
test_gfk = GenericRelation('RelationModel', content_type_field='gfk_ctype', object_id_field='gfk_id') test_gfk = GenericRelation('RelationModel', content_type_field='gfk_ctype', object_id_field='gfk_id')
exact = models.NullBooleanField()
def __str__(self): def __str__(self):
return force_text(self.pk) return force_text(self.pk)
@ -140,8 +141,8 @@ class RelationModel(models.Model):
m2m = models.ManyToManyField(RelatedModel, related_name='test_m2m') m2m = models.ManyToManyField(RelatedModel, related_name='test_m2m')
gfk_ctype = models.ForeignKey(ContentType) gfk_ctype = models.ForeignKey(ContentType, null=True)
gfk_id = models.IntegerField() gfk_id = models.IntegerField(null=True)
gfk = GenericForeignKey(ct_field='gfk_ctype', fk_field='gfk_id') gfk = GenericForeignKey(ct_field='gfk_ctype', fk_field='gfk_id')
def __str__(self): def __str__(self):

View File

@ -201,3 +201,11 @@ class ManagersRegressionTests(TestCase):
t.render(Context({'related': related})), t.render(Context({'related': related})),
''.join([force_text(relation.pk)] * 3), ''.join([force_text(relation.pk)] * 3),
) )
def test_field_can_be_called_exact(self):
# Make sure related managers core filters don't include an
# explicit `__exact` lookup that could be interpreted as a
# reference to a foreign `exact` field. refs #23940.
related = RelatedModel.objects.create(exact=False)
relation = related.test_fk.create()
self.assertEqual(related.test_fk.get(), relation)