mirror of
https://github.com/django/django.git
synced 2025-08-04 10:59:45 +00:00
Fixed #17648 -- Add for_concrete_model
to GenericForeignKey
.
Allows a `GenericForeignKey` to reference proxy models. The default for `for_concrete_model` is `True` to keep backwards compatibility. Also added the analog `for_concrete_model` kwarg to `generic_inlineformset_factory` to provide an API at the form level.
This commit is contained in:
parent
8dda8a5ecc
commit
48424adaba
6 changed files with 179 additions and 17 deletions
|
@ -6,7 +6,9 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.test import TestCase
|
||||
|
||||
from .models import (TaggedItem, ValuableTaggedItem, Comparison, Animal,
|
||||
Vegetable, Mineral, Gecko, Rock, ManualPK)
|
||||
Vegetable, Mineral, Gecko, Rock, ManualPK,
|
||||
ForProxyModelModel, ForConcreteModelModel,
|
||||
ProxyRelatedModel, ConcreteRelatedModel)
|
||||
|
||||
|
||||
class GenericRelationsTests(TestCase):
|
||||
|
@ -256,12 +258,120 @@ class TaggedItemForm(forms.ModelForm):
|
|||
widgets = {'tag': CustomWidget}
|
||||
|
||||
class GenericInlineFormsetTest(TestCase):
|
||||
"""
|
||||
Regression for #14572: Using base forms with widgets
|
||||
defined in Meta should not raise errors.
|
||||
"""
|
||||
|
||||
def test_generic_inlineformset_factory(self):
|
||||
"""
|
||||
Regression for #14572: Using base forms with widgets
|
||||
defined in Meta should not raise errors.
|
||||
"""
|
||||
Formset = generic_inlineformset_factory(TaggedItem, TaggedItemForm)
|
||||
form = Formset().forms[0]
|
||||
self.assertIsInstance(form['tag'].field.widget, CustomWidget)
|
||||
|
||||
def test_save_new_for_proxy(self):
|
||||
Formset = generic_inlineformset_factory(ForProxyModelModel,
|
||||
fields='__all__', for_concrete_model=False)
|
||||
|
||||
instance = ProxyRelatedModel.objects.create()
|
||||
|
||||
data = {
|
||||
'form-TOTAL_FORMS': '1',
|
||||
'form-INITIAL_FORMS': '0',
|
||||
'form-MAX_NUM_FORMS': '',
|
||||
'form-0-title': 'foo',
|
||||
}
|
||||
|
||||
formset = Formset(data, instance=instance, prefix='form')
|
||||
self.assertTrue(formset.is_valid())
|
||||
|
||||
new_obj, = formset.save()
|
||||
self.assertEqual(new_obj.obj, instance)
|
||||
|
||||
def test_save_new_for_concrete(self):
|
||||
Formset = generic_inlineformset_factory(ForProxyModelModel,
|
||||
fields='__all__', for_concrete_model=True)
|
||||
|
||||
instance = ProxyRelatedModel.objects.create()
|
||||
|
||||
data = {
|
||||
'form-TOTAL_FORMS': '1',
|
||||
'form-INITIAL_FORMS': '0',
|
||||
'form-MAX_NUM_FORMS': '',
|
||||
'form-0-title': 'foo',
|
||||
}
|
||||
|
||||
formset = Formset(data, instance=instance, prefix='form')
|
||||
self.assertTrue(formset.is_valid())
|
||||
|
||||
new_obj, = formset.save()
|
||||
self.assertNotIsInstance(new_obj.obj, ProxyRelatedModel)
|
||||
|
||||
|
||||
class ProxyRelatedModelTest(TestCase):
|
||||
def test_default_behavior(self):
|
||||
"""
|
||||
The default for for_concrete_model should be True
|
||||
"""
|
||||
base = ForConcreteModelModel()
|
||||
base.obj = rel = ProxyRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
base = ForConcreteModelModel.objects.get(pk=base.pk)
|
||||
rel = ConcreteRelatedModel.objects.get(pk=rel.pk)
|
||||
self.assertEqual(base.obj, rel)
|
||||
|
||||
def test_works_normally(self):
|
||||
"""
|
||||
When for_concrete_model is False, we should still be able to get
|
||||
an instance of the concrete class.
|
||||
"""
|
||||
base = ForProxyModelModel()
|
||||
base.obj = rel = ConcreteRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
base = ForProxyModelModel.objects.get(pk=base.pk)
|
||||
self.assertEqual(base.obj, rel)
|
||||
|
||||
def test_proxy_is_returned(self):
|
||||
"""
|
||||
Instances of the proxy should be returned when
|
||||
for_concrete_model is False.
|
||||
"""
|
||||
base = ForProxyModelModel()
|
||||
base.obj = ProxyRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
base = ForProxyModelModel.objects.get(pk=base.pk)
|
||||
self.assertIsInstance(base.obj, ProxyRelatedModel)
|
||||
|
||||
def test_query(self):
|
||||
base = ForProxyModelModel()
|
||||
base.obj = rel = ConcreteRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
self.assertEqual(rel, ConcreteRelatedModel.objects.get(bases__id=base.id))
|
||||
|
||||
def test_query_proxy(self):
|
||||
base = ForProxyModelModel()
|
||||
base.obj = rel = ProxyRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
self.assertEqual(rel, ProxyRelatedModel.objects.get(bases__id=base.id))
|
||||
|
||||
def test_generic_relation(self):
|
||||
base = ForProxyModelModel()
|
||||
base.obj = ProxyRelatedModel.objects.create()
|
||||
base.save()
|
||||
|
||||
base = ForProxyModelModel.objects.get(pk=base.pk)
|
||||
rel = ProxyRelatedModel.objects.get(pk=base.obj.pk)
|
||||
self.assertEqual(base, rel.bases.get())
|
||||
|
||||
def test_generic_relation_set(self):
|
||||
base = ForProxyModelModel()
|
||||
base.obj = ConcreteRelatedModel.objects.create()
|
||||
base.save()
|
||||
newrel = ConcreteRelatedModel.objects.create()
|
||||
|
||||
newrel.bases = [base]
|
||||
newrel = ConcreteRelatedModel.objects.get(pk=newrel.pk)
|
||||
self.assertEqual(base, newrel.bases.get())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue