mirror of
https://github.com/django/django.git
synced 2025-10-24 14:16:09 +00:00
Fixed #19733 - deprecated ModelForms without 'fields' or 'exclude', and added '__all__' shortcut
This also updates all dependent functionality, including modelform_factory and modelformset_factory, and the generic views `ModelFormMixin`, `CreateView` and `UpdateView` which gain a new `fields` attribute.
This commit is contained in:
@@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals
|
||||
import datetime
|
||||
import os
|
||||
from decimal import Decimal
|
||||
import warnings
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import FieldError
|
||||
@@ -30,19 +31,25 @@ if test_images:
|
||||
class ImageFileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ImageFile
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class OptionalImageFileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = OptionalImageFile
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ProductForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class PriceForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Price
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class BookForm(forms.ModelForm):
|
||||
@@ -66,11 +73,13 @@ class ExplicitPKForm(forms.ModelForm):
|
||||
class PostForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class DerivedPostForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = DerivedPost
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class CustomAuthorForm(forms.ModelForm):
|
||||
@@ -78,61 +87,79 @@ class CustomAuthorForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Author
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class FlexDatePostForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = FlexibleDatePost
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class BaseCategoryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class PartialArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = ('headline','pub_date')
|
||||
|
||||
|
||||
class RoykoForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Author
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TestArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class PartialArticleFormWithSlug(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields=('headline', 'slug', 'pub_date')
|
||||
fields = ('headline', 'slug', 'pub_date')
|
||||
|
||||
|
||||
class ArticleStatusForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ArticleStatus
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class InventoryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Inventory
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class SelectInventoryForm(forms.Form):
|
||||
items = forms.ModelMultipleChoiceField(Inventory.objects.all(), to_field_name='barcode')
|
||||
|
||||
|
||||
class CustomFieldForExclusionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = CustomFieldForExclusionModel
|
||||
fields = ['name', 'markup']
|
||||
|
||||
|
||||
class ShortCategory(forms.ModelForm):
|
||||
name = forms.CharField(max_length=5)
|
||||
slug = forms.CharField(max_length=5)
|
||||
@@ -140,30 +167,44 @@ class ShortCategory(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ImprovedArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ImprovedArticle
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ImprovedArticleWithParentLinkForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ImprovedArticleWithParentLink
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class BetterAuthorForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = BetterAuthor
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class AuthorProfileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AuthorProfile
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TextFileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = TextFile
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class BigIntForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = BigInt
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ModelFormWithMedia(forms.ModelForm):
|
||||
class Media:
|
||||
@@ -173,19 +214,25 @@ class ModelFormWithMedia(forms.ModelForm):
|
||||
}
|
||||
class Meta:
|
||||
model = TextFile
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class CommaSeparatedIntegerForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = CommaSeparatedInteger
|
||||
class Meta:
|
||||
model = CommaSeparatedInteger
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class PriceFormWithoutQuantity(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Price
|
||||
exclude = ('quantity',)
|
||||
|
||||
|
||||
class ColourfulItemForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ColourfulItem
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ModelFormBaseTest(TestCase):
|
||||
@@ -193,6 +240,25 @@ class ModelFormBaseTest(TestCase):
|
||||
self.assertEqual(list(BaseCategoryForm.base_fields),
|
||||
['name', 'slug', 'url'])
|
||||
|
||||
def test_missing_fields_attribute(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always", PendingDeprecationWarning)
|
||||
|
||||
class MissingFieldsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Category
|
||||
|
||||
# There is some internal state in warnings module which means that
|
||||
# if a warning has been seen already, the catch_warnings won't
|
||||
# have recorded it. The following line therefore will not work reliably:
|
||||
|
||||
# self.assertEqual(w[0].category, PendingDeprecationWarning)
|
||||
|
||||
# Until end of the deprecation cycle, should still create the
|
||||
# form as before:
|
||||
self.assertEqual(list(MissingFieldsForm.base_fields),
|
||||
['name', 'slug', 'url'])
|
||||
|
||||
def test_extra_fields(self):
|
||||
class ExtraFields(BaseCategoryForm):
|
||||
some_extra_field = forms.BooleanField()
|
||||
@@ -206,6 +272,33 @@ class ModelFormBaseTest(TestCase):
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = '__all__'
|
||||
|
||||
self.assertTrue(isinstance(ReplaceField.base_fields['url'],
|
||||
forms.fields.BooleanField))
|
||||
|
||||
def test_replace_field_variant_2(self):
|
||||
# Should have the same result as before,
|
||||
# but 'fields' attribute specified differently
|
||||
class ReplaceField(forms.ModelForm):
|
||||
url = forms.BooleanField()
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = ['url']
|
||||
|
||||
self.assertTrue(isinstance(ReplaceField.base_fields['url'],
|
||||
forms.fields.BooleanField))
|
||||
|
||||
def test_replace_field_variant_3(self):
|
||||
# Should have the same result as before,
|
||||
# but 'fields' attribute specified differently
|
||||
class ReplaceField(forms.ModelForm):
|
||||
url = forms.BooleanField()
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = [] # url will still appear, since it is explicit above
|
||||
|
||||
self.assertTrue(isinstance(ReplaceField.base_fields['url'],
|
||||
forms.fields.BooleanField))
|
||||
@@ -216,19 +309,11 @@ class ModelFormBaseTest(TestCase):
|
||||
|
||||
class Meta:
|
||||
model = Author
|
||||
fields = '__all__'
|
||||
|
||||
wf = AuthorForm({'name': 'Richard Lockridge'})
|
||||
self.assertTrue(wf.is_valid())
|
||||
|
||||
def test_limit_fields(self):
|
||||
class LimitFields(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = ['url']
|
||||
|
||||
self.assertEqual(list(LimitFields.base_fields),
|
||||
['url'])
|
||||
|
||||
def test_limit_nonexistent_field(self):
|
||||
expected_msg = 'Unknown field(s) (nonexistent) specified for Category'
|
||||
with self.assertRaisesMessage(FieldError, expected_msg):
|
||||
@@ -294,6 +379,7 @@ class ModelFormBaseTest(TestCase):
|
||||
"""
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
# MixModelForm is now an Article-related thing, because MixModelForm.Meta
|
||||
# overrides BaseCategoryForm.Meta.
|
||||
|
||||
@@ -348,6 +434,7 @@ class ModelFormBaseTest(TestCase):
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = '__all__'
|
||||
|
||||
class SubclassMeta(SomeCategoryForm):
|
||||
""" We can also subclass the Meta inner class to change the fields
|
||||
|
||||
Reference in New Issue
Block a user