Fix #19524 -- Incorrect caching of parents of unsaved model instances.
Thanks qcwxezdas for the report. Refs #13839.
This commit is contained in:
parent
37b3fd27ae
commit
e9c24bef74
|
@ -583,6 +583,15 @@ class Model(six.with_metaclass(ModelBase, object)):
|
||||||
|
|
||||||
if field:
|
if field:
|
||||||
setattr(self, field.attname, self._get_pk_val(parent._meta))
|
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:
|
if meta.proxy:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -692,7 +692,10 @@ class BaseInlineFormSet(BaseModelFormSet):
|
||||||
self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
|
self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.model._default_manager
|
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()
|
||||||
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
|
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
|
||||||
queryset=qs, **kwargs)
|
queryset=qs, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,9 @@ class ChildModel1Inline(admin.TabularInline):
|
||||||
class ChildModel2Inline(admin.StackedInline):
|
class ChildModel2Inline(admin.StackedInline):
|
||||||
model = ChildModel2
|
model = ChildModel2
|
||||||
|
|
||||||
|
# admin for #19524
|
||||||
|
class SightingInline(admin.TabularInline):
|
||||||
|
model = Sighting
|
||||||
|
|
||||||
site.register(TitleCollection, inlines=[TitleInline])
|
site.register(TitleCollection, inlines=[TitleInline])
|
||||||
# Test bug #12561 and #12778
|
# Test bug #12561 and #12778
|
||||||
|
@ -141,4 +144,5 @@ site.register(Holder4, Holder4Admin)
|
||||||
site.register(Author, AuthorAdmin)
|
site.register(Author, AuthorAdmin)
|
||||||
site.register(CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline])
|
site.register(CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline])
|
||||||
site.register(ProfileCollection, inlines=[ProfileInline])
|
site.register(ProfileCollection, inlines=[ProfileInline])
|
||||||
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
|
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
|
||||||
|
site.register(ExtraTerrestrial, inlines=[SightingInline])
|
||||||
|
|
|
@ -90,7 +90,6 @@ class Inner4Tabular(models.Model):
|
||||||
dummy = models.IntegerField(help_text="Awesome tabular help text is awesome.")
|
dummy = models.IntegerField(help_text="Awesome tabular help text is awesome.")
|
||||||
holder = models.ForeignKey(Holder4)
|
holder = models.ForeignKey(Holder4)
|
||||||
|
|
||||||
|
|
||||||
# Models for #12749
|
# Models for #12749
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
|
@ -133,6 +132,7 @@ class Chapter(models.Model):
|
||||||
|
|
||||||
|
|
||||||
# Models for #16838
|
# Models for #16838
|
||||||
|
|
||||||
class CapoFamiglia(models.Model):
|
class CapoFamiglia(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
@ -170,6 +170,17 @@ class ChildModel2(models.Model):
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return '/child_model2/'
|
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
|
# Other models
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ from .admin import InnerInline, TitleInline, site
|
||||||
from .models import (Holder, Inner, Holder2, Inner2, Holder3, Inner3, Person,
|
from .models import (Holder, Inner, Holder2, Inner2, Holder3, Inner3, Person,
|
||||||
OutfitItem, Fashionista, Teacher, Parent, Child, Author, Book, Profile,
|
OutfitItem, Fashionista, Teacher, Parent, Child, Author, Book, Profile,
|
||||||
ProfileCollection, ParentModelWithCustomPk, ChildModel1, ChildModel2,
|
ProfileCollection, ParentModelWithCustomPk, ChildModel1, ChildModel2,
|
||||||
Title)
|
Sighting, Title)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||||
|
@ -172,6 +172,23 @@ class TestInline(TestCase):
|
||||||
self.assertContains(response, child1_shortcut)
|
self.assertContains(response, child1_shortcut)
|
||||||
self.assertContains(response, child2_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',))
|
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||||
class TestInlineMedia(TestCase):
|
class TestInlineMedia(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue