Ticket #8160: model_formsets2.diff
File model_formsets2.diff, 7.5 KB (added by , 16 years ago) |
---|
-
django/forms/models.py
222 222 223 223 def modelform_factory(model, form=ModelForm, fields=None, exclude=None, 224 224 formfield_callback=lambda f: f.formfield()): 225 # HACK: we should be able to construct a ModelForm without creating 226 # and passing in a temporary inner class 227 class Meta: 228 pass 229 setattr(Meta, 'model', model) 230 setattr(Meta, 'fields', fields) 231 setattr(Meta, 'exclude', exclude) 225 import types 226 bases = () 227 if hasattr(form, 'Meta'): 228 bases = (form.Meta, ) 229 Meta = types.ClassType('Meta', bases, {}) 230 231 form_model = getattr(Meta, 'model', None) 232 if form_model: 233 if form_model != model: 234 raise Exception('model %s does not match model %s for ModelForm %s' % 235 (model, form_model, form)) 236 else: 237 setattr(Meta, 'model', model) 238 239 if fields: setattr(Meta, 'fields', fields) 240 if exclude: setattr(Meta, 'exclude', exclude) 241 232 242 class_name = model.__name__ + 'Form' 233 243 return ModelFormMetaclass(class_name, (form,), {'Meta': Meta, 234 244 'formfield_callback': formfield_callback}) … … 244 254 245 255 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, 246 256 queryset=None, **kwargs): 247 self.queryset = queryset 248 defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix} 257 self._queryset = queryset 249 258 if self.max_num > 0: 250 qs = self.get_queryset()[:self.max_num] 251 else: 252 qs = self.get_queryset() 253 defaults['initial'] = [model_to_dict(obj) for obj in qs] 259 self._queryset = self.get_queryset()[:self.max_num] 260 defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix} 261 defaults['initial'] = [model_to_dict(obj) for obj in self.get_queryset()] 254 262 defaults.update(kwargs) 255 263 super(BaseModelFormSet, self).__init__(**defaults) 256 264 257 265 def get_queryset(self): 258 if self.queryset is not None:259 return self.queryset260 return self. model._default_manager.get_query_set()266 if not self._queryset: 267 self._queryset = self.model._default_manager.get_query_set() 268 return self._queryset 261 269 262 def save_new(self, form, commit=True):263 """Saves and returns a new model instance for the given form."""264 return save_instance(form, self.model(), commit=commit)265 266 def save_existing(self, form, instance, commit=True):267 """Saves and returns an existing model instance for the given form."""268 return save_instance(form, instance, commit=commit)269 270 270 def save(self, commit=True): 271 271 """Saves model instances for every form, adding and changing instances 272 272 as necessary, and returns the list of instances. 273 273 """ 274 self.changed_objects = [] 275 self.deleted_objects = [] 276 self.new_objects = [] 277 saved_instances = [] 278 274 279 if not commit: 275 280 self.saved_forms = [] 276 281 def save_m2m(): 277 282 for form in self.saved_forms: 278 283 form.save_m2m() 279 284 self.save_m2m = save_m2m 280 return self.save_existing_objects(commit) + self.save_new_objects(commit)281 285 282 def save_existing_objects(self, commit=True): 283 self.changed_objects = [] 284 self.deleted_objects = [] 285 if not self.get_queryset(): 286 return [] 287 288 # Put the objects from self.get_queryset into a dict so they are easy to lookup by pk 289 existing_objects = {} 290 for obj in self.get_queryset(): 291 existing_objects[obj.pk] = obj 292 saved_instances = [] 293 for form in self.initial_forms: 294 obj = existing_objects[form.cleaned_data[self.model._meta.pk.attname]] 295 if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]: 296 self.deleted_objects.append(obj) 297 obj.delete() 298 else: 299 if form.changed_data: 300 self.changed_objects.append((obj, form.changed_data)) 301 saved_instances.append(self.save_existing(form, obj, commit=commit)) 302 if not commit: 303 self.saved_forms.append(form) 304 return saved_instances 305 306 def save_new_objects(self, commit=True): 307 self.new_objects = [] 308 for form in self.extra_forms: 286 for form in self.forms: 309 287 if not form.has_changed(): 310 288 continue 311 # If someone has marked an add form for deletion, don't save the312 # object.313 289 if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]: 314 continue 315 self.new_objects.append(self.save_new(form, commit=commit)) 316 if not commit: 317 self.saved_forms.append(form) 318 return self.new_objects 290 if form.instance and form.instance.pk: 291 self.deleted_objects.append(form.instance) 292 form.instance.delete() 293 else: 294 if form.instance.pk: 295 self.changed_objects.append((form.instance, form.changed_data)) 296 saved_instances.append(form.save(commit=commit)) 297 else: 298 self.new_objects.append(form.save(commit=commit)) 299 if not commit: 300 self.saved_forms.append(form) 301 return saved_instances + self.new_objects 319 302 320 303 def add_fields(self, form, index): 321 304 """Add a hidden field for the object's primary key.""" … … 324 307 form.fields[self._pk_field_name] = IntegerField(required=False, widget=HiddenInput) 325 308 super(BaseModelFormSet, self).add_fields(form, index) 326 309 310 def _construct_form(self, i, **kwargs): 311 defaults = {} 312 if i < self._initial_form_count: 313 defaults['instance'] = self.get_queryset()[i] 314 defaults.update(kwargs) 315 return super(BaseModelFormSet, self)._construct_form(i, **defaults) 316 317 327 318 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(), 328 319 formset=BaseModelFormSet, 329 320 extra=1, can_delete=False, can_order=False, … … 358 349 self._initial_form_count = 0 359 350 super(BaseInlineFormSet, self)._construct_forms() 360 351 352 def _construct_form(self, i, **kwargs): 353 defaults = {} 354 if i >= self._initial_form_count and self.instance: 355 defaults['instance'] = self.model(**{self.fk.get_attname(): self.instance.pk}) 356 defaults.update(kwargs) 357 return super(BaseInlineFormSet, self)._construct_form(i, **defaults) 358 361 359 def get_queryset(self): 362 360 """ 363 361 Returns this FormSet's queryset, but restricted to children of 364 362 self.instance 365 363 """ 366 kwargs = {self.fk.name: self.instance} 367 return self.model._default_manager.filter(**kwargs) 364 if not self._queryset: 365 kwargs = {self.fk.name: self.instance} 366 self._queryset = self.model._default_manager.filter(**kwargs) 367 return self._queryset 368 368 369 def save_new(self, form, commit=True):370 kwargs = {self.fk.get_attname(): self.instance.pk}371 new_obj = self.model(**kwargs)372 return save_instance(form, new_obj, commit=commit)373 369 374 370 def _get_foreign_key(parent_model, model, fk_name=None): 375 371 """