Ticket #13095: 13095-formfield_callback-r13517.diff
File 13095-formfield_callback-r13517.diff, 7.5 KB (added by , 14 years ago) |
---|
-
django/forms/models.py
150 150 data[f.name] = f.value_from_object(instance) 151 151 return data 152 152 153 def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback= lambda f, **kwargs: f.formfield(**kwargs)):153 def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=None): 154 154 """ 155 155 Returns a ``SortedDict`` containing form fields for the given model. 156 156 … … 175 175 kwargs = {'widget': widgets[f.name]} 176 176 else: 177 177 kwargs = {} 178 formfield = formfield_callback(f, **kwargs) 178 179 if formfield_callback is None: 180 formfield = f.formfield(**kwargs) 181 else: 182 formfield = formfield_callback(f, **kwargs) 183 179 184 if formfield: 180 185 field_list.append((f.name, formfield)) 181 186 else: … … 198 203 199 204 class ModelFormMetaclass(type): 200 205 def __new__(cls, name, bases, attrs): 201 formfield_callback = attrs.pop('formfield_callback', 202 lambda f, **kwargs: f.formfield(**kwargs)) 206 formfield_callback = attrs.pop('formfield_callback', None) 203 207 try: 204 208 parents = [b for b in bases if issubclass(b, ModelForm)] 205 209 except NameError: … … 376 380 __metaclass__ = ModelFormMetaclass 377 381 378 382 def modelform_factory(model, form=ModelForm, fields=None, exclude=None, 379 formfield_callback= lambda f: f.formfield()):383 formfield_callback=None): 380 384 # Create the inner Meta class. FIXME: ideally, we should be able to 381 385 # construct a ModelForm without creating and passing in a temporary 382 386 # inner class. … … 658 662 form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=HiddenInput) 659 663 super(BaseModelFormSet, self).add_fields(form, index) 660 664 661 def modelformset_factory(model, form=ModelForm, formfield_callback= lambda f: f.formfield(),665 def modelformset_factory(model, form=ModelForm, formfield_callback=None, 662 666 formset=BaseModelFormSet, 663 667 extra=1, can_delete=False, can_order=False, 664 668 max_num=None, fields=None, exclude=None): … … 813 817 formset=BaseInlineFormSet, fk_name=None, 814 818 fields=None, exclude=None, 815 819 extra=3, can_order=False, can_delete=True, max_num=None, 816 formfield_callback= lambda f: f.formfield()):820 formfield_callback=None): 817 821 """ 818 822 Returns an ``InlineFormSet`` for the given kwargs. 819 823 -
tests/regressiontests/model_forms_regress/tests.py
250 250 form.is_valid() 251 251 # self.assertTrue(form.is_valid()) 252 252 # self.assertEquals(form.cleaned_data['url'], 'http://example.com/test') 253 254 255 class FormFieldCallbackTests(TestCase): 256 257 def test_baseform_with_widgets_in_meta(self): 258 """ 259 Regression for #13095: Using base forms with widgets 260 defined in Meta should not raise errors. 261 """ 262 widget = forms.Textarea() 263 264 class BaseForm(forms.ModelForm): 265 class Meta: 266 model = Person 267 widgets = {'name': widget} 268 269 Form = modelform_factory(Person, form=BaseForm) 270 self.assertTrue(Form.base_fields['name'].widget is widget) 271 272 def test_custom_callback(self): 273 """Test that a custom formfield_callback is used if provided""" 274 275 callback_args = [] 276 277 def callback(db_field, **kwargs): 278 callback_args.append((db_field, kwargs)) 279 return db_field.formfield(**kwargs) 280 281 widget = forms.Textarea() 282 283 class BaseForm(forms.ModelForm): 284 class Meta: 285 model = Person 286 widgets = {'name': widget} 287 288 _ = modelform_factory(Person, form=BaseForm, 289 formfield_callback=callback) 290 id_field, name_field = Person._meta.fields 291 292 self.assertEqual(callback_args, 293 [(id_field, {}), (name_field, {'widget': widget})]) 294 295 def test_bad_callback(self): 296 # A bad callback provided by user still gives an error 297 self.assertRaises(TypeError, modelform_factory, Person, 298 widgets={'name': forms.Textarea()}, 299 formfield_callback=lambda f: f.formfield()) -
tests/regressiontests/model_formsets_regress/tests.py
1 from django.forms.models import modelform_factory, inlineformset_factory 1 from django import forms 2 from django.forms.models import modelform_factory, inlineformset_factory, modelformset_factory 2 3 from django.test import TestCase 3 4 4 5 from models import User, UserSite, Restaurant, Manager 5 6 7 6 8 class InlineFormsetTests(TestCase): 7 9 def test_formset_over_to_field(self): 8 10 "A formset over a ForeignKey with a to_field can be saved. Regression for #10243" … … 156 158 # you can create a formset with an instance of None 157 159 form = Form(instance=None) 158 160 formset = FormSet(instance=None) 161 162 163 class CustomWidget(forms.CharField): 164 pass 165 166 167 class UserSiteForm(forms.ModelForm): 168 class Meta: 169 model = UserSite 170 widgets = {'data': CustomWidget} 171 172 173 class Callback(object): 174 175 def __init__(self): 176 self.log = [] 177 178 def __call__(self, db_field, **kwargs): 179 self.log.append((db_field, kwargs)) 180 return db_field.formfield(**kwargs) 181 182 183 class FormfieldCallbackTests(TestCase): 184 """ 185 Regression for #13095: Using base forms with widgets 186 defined in Meta should not raise errors. 187 """ 188 189 def test_inlineformset_factory_default(self): 190 Formset = inlineformset_factory(User, UserSite, form=UserSiteForm) 191 form = Formset({}).forms[0] 192 self.assertTrue(isinstance(form['data'].field.widget, CustomWidget)) 193 194 def test_modelformset_factory_default(self): 195 Formset = modelformset_factory(UserSite, form=UserSiteForm) 196 form = Formset({}).forms[0] 197 self.assertTrue(isinstance(form['data'].field.widget, CustomWidget)) 198 199 def assertCallbackCalled(self, callback): 200 id_field, user_field, data_field = UserSite._meta.fields 201 expected_log = [ 202 (id_field, {}), 203 (user_field, {}), 204 (data_field, {'widget': CustomWidget}), 205 ] 206 self.assertEqual(callback.log, expected_log) 207 208 def test_inlineformset_custom_callback(self): 209 callback = Callback() 210 inlineformset_factory(User, UserSite, form=UserSiteForm, 211 formfield_callback=callback) 212 self.assertCallbackCalled(callback) 213 214 def test_modelformset_custom_callback(self): 215 callback = Callback() 216 modelformset_factory(UserSite, form=UserSiteForm, 217 formfield_callback=callback) 218 self.assertCallbackCalled(callback)