Changeset 6655
- Timestamp:
- 11/06/07 15:53:15 (1 year ago)
- Files:
-
- django/branches/newforms-admin/django/newforms/models.py (modified) (4 diffs)
- django/branches/newforms-admin/tests/modeltests/model_formsets (added)
- django/branches/newforms-admin/tests/modeltests/model_formsets/__init__.py (added)
- django/branches/newforms-admin/tests/modeltests/model_formsets/models.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/newforms-admin/django/newforms/models.py
r6654 r6655 16 16 __all__ = ( 17 17 'save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields', 18 ' ModelChoiceField', 'ModelMultipleChoiceField', 'formset_for_model',19 ' inline_formset'18 'formset_for_model', 'formset_for_queryset', 'inline_formset', 19 'ModelChoiceField', 'ModelMultipleChoiceField', 20 20 ) 21 21 … … 238 238 class BaseModelFormSet(BaseFormSet): 239 239 """ 240 A ``FormSet`` attatched to a particular model or sequence of model instances.240 A ``FormSet`` for editing a queryset and/or adding new objects to it. 241 241 """ 242 242 model = None 243 244 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, instances=None): 245 self.instances = instances243 queryset = None 244 245 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None): 246 246 kwargs = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix} 247 if instances:248 kwargs['initial'] = [initial_data( instance) for instance in instances]247 if self.queryset: 248 kwargs['initial'] = [initial_data(obj) for obj in self.get_queryset()] 249 249 super(BaseModelFormSet, self).__init__(**kwargs) 250 251 def get_queryset(self): 252 return self.queryset._clone() 250 253 251 254 def save_new(self, form, commit=True): … … 261 264 as necessary, and returns the list of instances. 262 265 """ 266 return self.save_existing_objects(commit) + self.save_new_objects(commit) 267 268 def save_existing_objects(self, commit=True): 269 if not self.queryset: 270 return [] 271 # Put the objects from self.get_queryset into a dict so they are easy to lookup by pk 272 existing_objects = {} 273 for obj in self.get_queryset(): 274 existing_objects[obj._get_pk_val()] = obj 263 275 saved_instances = [] 264 # put self.instances into a dict so they are easy to lookup by pk 265 instances = {} 266 for instance in self.instances: 267 instances[instance._get_pk_val()] = instance 268 if self.instances: 269 # update/save existing instances 270 for form in self.change_forms: 271 instance = instances[form.cleaned_data[self.model._meta.pk.attname]] 272 if self.deletable and form.cleaned_data[DELETION_FIELD_NAME]: 273 instance.delete() 274 else: 275 saved_instances.append(self.save_instance(form, instance, commit=commit)) 276 # create/save new instances 276 for form in self.change_forms: 277 obj = existing_objects[form.cleaned_data[self.model._meta.pk.attname]] 278 if self.deletable and form.cleaned_data[DELETION_FIELD_NAME]: 279 obj.delete() 280 else: 281 saved_instances.append(self.save_instance(form, obj, commit=commit)) 282 return saved_instances 283 284 def save_new_objects(self, commit=True): 285 new_objects = [] 277 286 for form in self.add_forms: 278 287 if form.is_empty(): 279 288 continue 280 saved_instances.append(self.save_new(form, commit=commit)) 281 return saved_instances 289 # If someone has marked an add form for deletion, don't save the 290 # object. At some point it would be nice if we didn't display 291 # the deletion widget for add forms. 292 if self.deletable and form.cleaned_data[DELETION_FIELD_NAME]: 293 continue 294 new_objects.append(self.save_new(form, commit=commit)) 295 return new_objects 282 296 283 297 def add_fields(self, form, index): … … 287 301 super(BaseModelFormSet, self).add_fields(form, index) 288 302 289 def formset_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield(), formset=BaseModelFormSet, extra=1, orderable=False, deletable=False, fields=None): 290 form = form_for_model(model, form=form, fields=fields, formfield_callback=formfield_callback) 303 def formset_for_queryset(queryset, form=BaseForm, formfield_callback=lambda f: f.formfield(), 304 formset=BaseModelFormSet, extra=1, orderable=False, deletable=False, fields=None): 305 """ 306 Returns a FormSet class for the given QuerySet. This FormSet will contain 307 change forms for every instance in the QuerySet as well as the number of 308 add forms specified by ``extra``. 309 310 Provide ``extra`` to determine the number of add forms to display. 311 312 Provide ``deletable`` if you want to allow the formset to delete any 313 objects in the given queryset. 314 315 Provide ``form`` if you want to use a custom BaseForm subclass. 316 317 Provide ``formfield_callback`` if you want to define different logic for 318 determining the formfield for a given database field. It's a callable that 319 takes a database Field instance and returns a form Field instance. 320 321 Provide ``formset`` if you want to use a custom BaseModelFormSet subclass. 322 """ 323 form = form_for_model(queryset.model, form=form, fields=fields, formfield_callback=formfield_callback) 291 324 FormSet = formset_for_form(form, formset, extra, orderable, deletable) 292 FormSet.model = model 325 FormSet.model = queryset.model 326 FormSet.queryset = queryset 293 327 return FormSet 328 329 def formset_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield(), 330 formset=BaseModelFormSet, extra=1, orderable=False, deletable=False, fields=None): 331 """ 332 Returns a FormSet class for the given Django model class. This FormSet 333 will contain change forms for every instance of the given model as well 334 as the number of add forms specified by ``extra``. 335 336 This is essentially the same as ``formset_for_queryset``, but automatically 337 uses the model's default manager to determine the queryset. 338 """ 339 qs = model._default_manager.all() 340 return formset_for_queryset(qs, form, formfield_callback, formset, extra, orderable, deletable, fields) 294 341 295 342 class InlineFormset(BaseModelFormSet): 296 343 """A formset for child objects related to a parent.""" 297 def __init__(self, instance =None, data=None, files=None):344 def __init__(self, instance, data=None, files=None): 298 345 from django.db.models.fields.related import RelatedObject 299 346 self.instance = instance 300 347 # is there a better way to get the object descriptor? 301 348 self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name() 302 super(InlineFormset, self).__init__(data, files, instances=self.get_inline_objects(), prefix=self.rel_name) 303 304 def get_inline_objects(self): 305 if self.instance is None: 306 return [] 307 return getattr(self.instance, self.rel_name).all() 349 super(InlineFormset, self).__init__(data, files, prefix=self.rel_name) 350 351 def get_queryset(self): 352 """ 353 Returns this FormSet's queryset, but restricted to children of 354 self.instance 355 """ 356 kwargs = {self.fk.name: self.instance} 357 return self.queryset.filter(**kwargs) 308 358 309 359 def save_new(self, form, commit=True):
