Skip to content

Commit

Permalink
[1.5.x] Fix #19524 -- Incorrect caching of parents of unsaved model i…
Browse files Browse the repository at this point in the history
…nstances.

Thanks qcwxezdas for the report. Refs #13839.

Backport of e9c24be.
  • Loading branch information
aaugustin committed Dec 28, 2012
1 parent be42590 commit 5097d3c
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 4 deletions.
9 changes: 9 additions & 0 deletions django/db/models/base.py
Expand Up @@ -583,6 +583,15 @@ def save_base(self, raw=False, cls=None, origin=None, force_insert=False,

if field:
setattr(self, field.attname, self._get_pk_val(parent._meta))
# Since we didn't have an instance of the parent handy, we
# set attname directly, bypassing the descriptor.
# Invalidate the related object cache, in case it's been
# accidentally populated. A fresh instance will be
# re-built from the database if necessary.
cache_name = field.get_cache_name()
if hasattr(self, cache_name):
delattr(self, cache_name)

if meta.proxy:
return

Expand Down
5 changes: 4 additions & 1 deletion django/forms/models.py
Expand Up @@ -692,7 +692,10 @@ def __init__(self, data=None, files=None, instance=None,
self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
if queryset is None:
queryset = self.model._default_manager
qs = queryset.filter(**{self.fk.name: self.instance})
if self.instance.pk:
qs = queryset.filter(**{self.fk.name: self.instance})
else:
qs = queryset.none()

This comment has been minimized.

Copy link
@charettes

charettes Jan 22, 2013

Member

This introduce a regression with related managers on 1.5.X since none returns an EmptyQuerySet instance while it works fine on master since none sets the underlying query to empty while returning a queryset.__class__ instance. I'll open a ticket with a failing test case.

This comment has been minimized.

Copy link
@aaugustin

aaugustin Jan 24, 2013

Author Member

I saw that you and Anssi came up with a patch in https://code.djangoproject.com/ticket/19652.

For added safety I committed 9328ef0.

super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
queryset=qs, **kwargs)

Expand Down
6 changes: 5 additions & 1 deletion tests/regressiontests/admin_inlines/admin.py
Expand Up @@ -124,6 +124,9 @@ class ChildModel1Inline(admin.TabularInline):
class ChildModel2Inline(admin.StackedInline):
model = ChildModel2

# admin for #19524
class SightingInline(admin.TabularInline):
model = Sighting

site.register(TitleCollection, inlines=[TitleInline])
# Test bug #12561 and #12778
Expand All @@ -141,4 +144,5 @@ class ChildModel2Inline(admin.StackedInline):
site.register(Author, AuthorAdmin)
site.register(CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline])
site.register(ProfileCollection, inlines=[ProfileInline])
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
site.register(ExtraTerrestrial, inlines=[SightingInline])
13 changes: 12 additions & 1 deletion tests/regressiontests/admin_inlines/models.py
Expand Up @@ -90,7 +90,6 @@ class Inner4Tabular(models.Model):
dummy = models.IntegerField(help_text="Awesome tabular help text is awesome.")
holder = models.ForeignKey(Holder4)


# Models for #12749

class Person(models.Model):
Expand Down Expand Up @@ -133,6 +132,7 @@ class Chapter(models.Model):


# Models for #16838

class CapoFamiglia(models.Model):
name = models.CharField(max_length=100)

Expand Down Expand Up @@ -170,6 +170,17 @@ class ChildModel2(models.Model):
def get_absolute_url(self):
return '/child_model2/'

# Models for #19524

class LifeForm(models.Model):
pass

class ExtraTerrestrial(LifeForm):
name = models.CharField(max_length=100)

class Sighting(models.Model):
et = models.ForeignKey(ExtraTerrestrial)
place = models.CharField(max_length=100)

# Other models

Expand Down
19 changes: 18 additions & 1 deletion tests/regressiontests/admin_inlines/tests.py
Expand Up @@ -12,7 +12,7 @@
from .models import (Holder, Inner, Holder2, Inner2, Holder3, Inner3, Person,
OutfitItem, Fashionista, Teacher, Parent, Child, Author, Book, Profile,
ProfileCollection, ParentModelWithCustomPk, ChildModel1, ChildModel2,
Title)
Sighting, Title)


@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
Expand Down Expand Up @@ -172,6 +172,23 @@ def test_custom_pk_shortcut(self):
self.assertContains(response, child1_shortcut)
self.assertContains(response, child2_shortcut)

def test_create_inlines_on_inherited_model(self):
"""
Ensure that an object can be created with inlines when it inherits
another class. Bug #19524.
"""
data = {
'name': 'Martian',
'sighting_set-TOTAL_FORMS': 1,
'sighting_set-INITIAL_FORMS': 0,
'sighting_set-MAX_NUM_FORMS': 0,
'sighting_set-0-place': 'Zone 51',
'_save': 'Save',
}
response = self.client.post('/admin/admin_inlines/extraterrestrial/add/', data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Sighting.objects.filter(et__name='Martian').count(), 1)


@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class TestInlineMedia(TestCase):
Expand Down

0 comments on commit 5097d3c

Please sign in to comment.