Ticket #4667: newforms-admin-6477-generic-edit-inline.patch
File newforms-admin-6477-generic-edit-inline.patch, 9.8 KB (added by , 17 years ago) |
---|
-
django/contrib/admin/options.py
commit 015c9b884376c82a1b53ccd11728449d1b119d26 Author: Honza Král <Honza.Kral@gmail.com> Date: Tue Oct 2 18:18:24 2007 +0200 Added generic edit inline patch http://code.djangoproject.com/ticket/4667 diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index bab9580..d650a1e 100644
a b 1 1 from django import oldforms, template 2 2 from django import newforms as forms 3 3 from django.newforms.formsets import all_valid 4 from django.contrib.contenttypes.models import ContentType5 4 from django.contrib.admin import widgets 6 5 from django.contrib.admin.util import get_deleted_objects 7 6 from django.core.exceptions import ImproperlyConfigured, PermissionDenied … … class ModelAdmin(BaseModelAdmin): 451 450 return HttpResponseRedirect("../") 452 451 453 452 def render_change_form(self, model, context, add=False, change=False, form_url=''): 453 from django.contrib.contenttypes.models import ContentType 454 454 opts = model._meta 455 455 app_label = opts.app_label 456 456 ordered_objects = opts.get_ordered_objects() … … class InlineModelAdmin(BaseModelAdmin): 721 721 template = None 722 722 verbose_name = None 723 723 verbose_name_plural = None 724 formset = None 724 725 725 726 def __init__(self, parent_model, admin_site): 726 727 self.admin_site = admin_site … … class InlineModelAdmin(BaseModelAdmin): 738 739 fields = flatten_fieldsets(self.declared_fieldsets) 739 740 else: 740 741 fields = None 741 return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) 742 return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, 743 formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset) 742 744 743 745 def formset_change(self, request, obj): 744 746 """Returns an InlineFormSet class for use in admin change views.""" … … class InlineModelAdmin(BaseModelAdmin): 746 748 fields = flatten_fieldsets(self.declared_fieldsets) 747 749 else: 748 750 fields = None 749 return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) 751 return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, 752 formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset) 750 753 751 754 def fieldsets_add(self, request): 752 755 if self.declared_fieldsets: -
django/contrib/contenttypes/generic.py
diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index b738a26..bdf9985 100644
a b class GenericRel(ManyToManyRel): 260 260 self.multiple = True 261 261 assert not (self.raw_id_admin and self.filter_interface), \ 262 262 "Generic relations may not use both raw_id_admin and filter_interface" 263 264 from django.newforms.models import BaseModelFormSet, formset_for_model, save_instance 265 from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets 266 267 def get_foreign_key(model, ct_field_name, id_field_name): 268 opts = model._meta 269 # avoid circular import 270 from django.db.models import ForeignKey 271 from django.contrib.contenttypes.models import ContentType 272 opts = model._meta 273 274 # if there is no field called `ct_field_name` let the exception propagate 275 ct = opts.get_field(ct_field_name) 276 if not isinstance(ct, ForeignKey) or ct.rel.to != ContentType: 277 raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % (ct_field_name)) 278 279 # if there is no field called `id_field_name` let the exception propagate 280 obj_id = opts.get_field(id_field_name) 281 282 return ct, obj_id 283 284 def inline_formset(model, ct_field_name, id_field_name, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield(), formset=None): 285 """ 286 Returns an ``InlineFormset`` for the given kwargs. 287 288 You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey`` 289 to ``parent_model``. 290 """ 291 ct, obj_id = get_foreign_key(model, ct_field_name, id_field_name) 292 # let the formset handle object deletion by default 293 FormSet = formset_for_model(model, formset=formset or GenericInlineFormset, fields=fields, 294 formfield_callback=formfield_callback, 295 extra=extra, orderable=orderable, 296 deletable=deletable) 297 # HACK: remove the ForeignKey to the parent from every form 298 # This should be done a line above before we pass 'fields' to formset_for_model 299 # an 'omit' argument would be very handy here 300 try: 301 del FormSet.form_class.base_fields[ct.name] 302 del FormSet.form_class.base_fields[obj_id.name] 303 except KeyError: 304 pass 305 FormSet.ct = ct 306 FormSet.obj_id = obj_id 307 return FormSet 308 309 class GenericInlineFormset(BaseModelFormSet): 310 """A formset for child objects related to a parent.""" 311 def __init__(self, instance=None, data=None, files=None): 312 self.instance = instance 313 # is there a better way to get the object descriptor? 314 self.rel_name = self.ct.name + '_' + self.obj_id.name 315 super(GenericInlineFormset, self).__init__(data, files, instances=self.get_inline_objects(), prefix=self.rel_name) 316 317 def get_inline_objects(self): 318 # This import is done here to avoid circular import importing this module 319 from django.contrib.contenttypes.models import ContentType 320 if self.instance is None: 321 return [] 322 return self.model._default_manager.filter( **{ 323 self.ct.name : ContentType.objects.get_for_model(self.instance), 324 self.obj_id.name : self.instance._get_pk_val() 325 }) 326 327 def save_new(self, form, commit=True): 328 # This import is done here to avoid circular import importing this module 329 from django.contrib.contenttypes.models import ContentType 330 kwargs = { 331 self.ct.get_attname(): ContentType.objects.get_for_model(self.instance).id, 332 self.obj_id.get_attname(): self.instance._get_pk_val(), 333 } 334 new_obj = self.model(**kwargs) 335 return save_instance(form, new_obj, commit=commit) 336 337 class GenericInlineModelAdmin(InlineModelAdmin): 338 ct_field_name = None 339 id_field_name = None 340 def formset_add(self, request): 341 """Returns an GenericInlineFormSet class for use in admin add views.""" 342 if self.declared_fieldsets: 343 fields = flatten_fieldsets(self.declared_fieldsets) 344 else: 345 fields = None 346 return inline_formset(self.model, self.ct_field_name, self.id_field_name, fields=fields, 347 formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset) 348 349 def formset_change(self, request, obj): 350 """Returns an GenericInlineFormSet class for use in admin change views.""" 351 if self.declared_fieldsets: 352 fields = flatten_fieldsets(self.declared_fieldsets) 353 else: 354 fields = None 355 return inline_formset(self.model, self.ct_field_name, self.id_field_name, fields=fields, 356 formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset) 357 358 class GenericStackedInline(GenericInlineModelAdmin): 359 template = 'admin/edit_inline/stacked.html' 360 361 class GenericTabularInline(GenericInlineModelAdmin): 362 template = 'admin/edit_inline/tabular.html' 363 -
django/db/models/query.py
diff --git a/django/db/models/query.py b/django/db/models/query.py index 4d0d295..636ae72 100644
a b from django.db.models import signals, loading 5 5 from django.dispatch import dispatcher 6 6 from django.utils.datastructures import SortedDict 7 7 from django.utils.encoding import smart_unicode 8 from django.contrib.contenttypes import generic9 8 import datetime 10 9 import operator 11 10 import re … … def lookup_inner(path, lookup_type, value, opts, table, column): 1119 1118 1120 1119 def delete_objects(seen_objs): 1121 1120 "Iterate through a list of seen classes, and remove any instances that are referred to" 1121 from django.contrib.contenttypes import generic 1122 1122 qn = connection.ops.quote_name 1123 1123 ordered_classes = seen_objs.keys() 1124 1124 ordered_classes.reverse() -
django/newforms/models.py
diff --git a/django/newforms/models.py b/django/newforms/models.py index 5fdbc4d..a27a9e8 100644
a b def get_foreign_key(parent_model, model, fk_name=None): 338 338 raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model)) 339 339 return fk 340 340 341 def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield() ):341 def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield(), formset=None): 342 342 """ 343 343 Returns an ``InlineFormset`` for the given kwargs. 344 344 … … def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orde 347 347 """ 348 348 fk = get_foreign_key(parent_model, model, fk_name=fk_name) 349 349 # let the formset handle object deletion by default 350 FormSet = formset_for_model(model, formset= InlineFormset, fields=fields,350 FormSet = formset_for_model(model, formset=formset or InlineFormset, fields=fields, 351 351 formfield_callback=formfield_callback, 352 352 extra=extra, orderable=orderable, 353 353 deletable=deletable)