Ticket #4667: newforms-admin-6426-generic-edit-inline.patch

File newforms-admin-6426-generic-edit-inline.patch, 9.4 KB (added by Honza Král, 17 years ago)

Matching django version 6426

  • django/contrib/admin/options.py

    commit 5b9f454eef18f63c85c35e3f2ee903723199b508
    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 9018472..ef98bc0 100644
    a b class InlineModelAdmin(BaseModelAdmin):  
    694694    template = None
    695695    verbose_name = None
    696696    verbose_name_plural = None
     697    formset = None
    697698
    698699    def __init__(self, parent_model, admin_site):
    699700        self.admin_site = admin_site
    class InlineModelAdmin(BaseModelAdmin):  
    711712            fields = flatten_fieldsets(self.declared_fieldsets)
    712713        else:
    713714            fields = None
    714         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)
     715        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields,
     716                    formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset)
    715717
    716718    def formset_change(self, request, obj):
    717719        """Returns an InlineFormSet class for use in admin change views."""
    class InlineModelAdmin(BaseModelAdmin):  
    719721            fields = flatten_fieldsets(self.declared_fieldsets)
    720722        else:
    721723            fields = None
    722         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)
     724        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields,
     725                    formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset)
    723726
    724727    def fieldsets_add(self, request):
    725728        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..0612ffc 100644
    a b class GenericRel(ManyToManyRel):  
    260260        self.multiple = True
    261261        assert not (self.raw_id_admin and self.filter_interface), \
    262262            "Generic relations may not use both raw_id_admin and filter_interface"
     263
     264from django.newforms.models import InlineFormset, save_instance
     265class GenericInlineFormset(InlineFormset):
     266
     267    @classmethod
     268    def add_fk(cls, parent_model, model, fk_name):
     269        from django.template.defaultfilters import slugify
     270        assert ':' in fk_name, "Supply valid content_type:object_id as fk_name."
     271
     272        opts = model._meta
     273        ct_field_name, id_field_name = fk_name.split(':')
     274        ct = opts.get_field( ct_field_name )
     275        obj_id = opts.get_field( id_field_name )
     276        # HACK: remove the ForeignKey to the parent from every form
     277        # This should be done a line above before we pass 'fields' to formset_for_model
     278        # an 'omit' argument would be very handy here
     279        try:
     280            del cls.form_class.base_fields[ct.name]
     281            del cls.form_class.base_fields[obj_id.name]
     282        except KeyError:
     283            pass
     284
     285        cls.parent_model = parent_model
     286        cls.model = model
     287        cls.ct_field_name = ct_field_name
     288        cls.id_field_name = id_field_name
     289        cls.ct = ct
     290        cls.obj_id = obj_id
     291        cls.rel_name = slugify(fk_name)
     292
     293    def get_inline_objects(self):
     294        # This import is done here to avoid circular import importing this module
     295        from django.contrib.contenttypes.models import ContentType
     296        if self.instance is None:
     297            return []
     298        return self.model._default_manager.filter( **{
     299                self.ct_field_name : ContentType.objects.get_for_model(self.instance),
     300                self.id_field_name : self.instance._get_pk_val()
     301            })
     302
     303    def save_new(self, form, commit=True):
     304        # This import is done here to avoid circular import importing this module
     305        from django.contrib.contenttypes.models import ContentType
     306        kwargs = {
     307            self.ct.get_attname(): ContentType.objects.get_for_model(self.instance).id,
     308            self.obj_id.get_attname(): self.instance._get_pk_val(),
     309        }
     310        new_obj = self.model(**kwargs)
     311        return save_instance(form, new_obj, commit=commit)
  • django/newforms/models.py

    diff --git a/django/newforms/models.py b/django/newforms/models.py
    index 5c4dc08..61b8dc7 100644
    a b def formset_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formf  
    295295class InlineFormset(BaseModelFormSet):
    296296    """A formset for child objects related to a parent."""
    297297    def __init__(self, instance=None, data=None, files=None):
    298         from django.db.models.fields.related import RelatedObject
    299298        self.instance = instance
    300299        # is there a better way to get the object descriptor?
    301         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
    302300        super(InlineFormset, self).__init__(data, files, instances=self.get_inline_objects(), prefix=self.rel_name)
    303301
    304302    def get_inline_objects(self):
    class InlineFormset(BaseModelFormSet):  
    311309        new_obj = self.model(**kwargs)
    312310        return save_instance(form, new_obj, commit=commit)
    313311
    314 def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield()):
     312    @classmethod
     313    def add_fk(cls, parent_model, model, fk_name):
     314        from django.db.models import ForeignKey
     315        from django.db.models.fields.related import RelatedObject
     316        opts = model._meta
     317        # figure out what the ForeignKey from model to parent_model is
     318        if fk_name is None:
     319            fks_to_parent = [f for f in opts.fields if isinstance(f, ForeignKey) and f.rel.to == parent_model]
     320            if len(fks_to_parent) == 1:
     321                fk = fks_to_parent[0]
     322            elif len(fks_to_parent) == 0:
     323                raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
     324            else:
     325                raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
     326        else:
     327            fks_to_parent = [f for f in opts.fields if f.name == fk_name]
     328            if len(fks_to_parent) == 1:
     329                fk = fks_to_parent[0]
     330                if not isinstance(fk, ForeignKey) or fk.rel.to != parent_model:
     331                    raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
     332            elif len(fks_to_parent) == 0:
     333                raise Exception("%s has no field named '%s'" % (model, fk_name))
     334        # HACK: remove the ForeignKey to the parent from every form
     335        # This should be done a line above before we pass 'fields' to formset_for_model
     336        # an 'omit' argument would be very handy here
     337        try:
     338            del cls.form_class.base_fields[fk.name]
     339        except KeyError:
     340            pass
     341
     342        cls.parent_model = parent_model
     343        cls.fk_name = fk.name
     344        cls.rel_name = RelatedObject(fk.rel.to, model, fk).get_accessor_name()
     345        cls.fk = fk
     346
     347def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False,
     348                    deletable=True, formfield_callback=lambda f: f.formfield(), formset=None):
    315349    """
    316350    Returns an ``InlineFormset`` for the given kwargs.
    317351
    318352    You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
    319353    to ``parent_model``.
    320354    """
    321     from django.db.models import ForeignKey
    322     opts = model._meta
    323     # figure out what the ForeignKey from model to parent_model is
    324     if fk_name is None:
    325         fks_to_parent = [f for f in opts.fields if isinstance(f, ForeignKey) and f.rel.to == parent_model]
    326         if len(fks_to_parent) == 1:
    327             fk = fks_to_parent[0]
    328         elif len(fks_to_parent) == 0:
    329             raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
    330         else:
    331             raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
    332     else:
    333         fks_to_parent = [f for f in opts.fields if f.name == fk_name]
    334         if len(fks_to_parent) == 1:
    335             fk = fks_to_parent[0]
    336             if not isinstance(fk, ForeignKey) or fk.rel.to != parent_model:
    337                 raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
    338         elif len(fks_to_parent) == 0:
    339             raise Exception("%s has no field named '%s'" % (model, fk_name))
    340355    # let the formset handle object deletion by default
    341     FormSet = formset_for_model(model, formset=InlineFormset, fields=fields,
     356    FormSet = formset_for_model(model, formset=formset or InlineFormset, fields=fields,
    342357                                formfield_callback=formfield_callback,
    343358                                extra=extra, orderable=orderable,
    344359                                deletable=deletable)
    345     # HACK: remove the ForeignKey to the parent from every form
    346     # This should be done a line above before we pass 'fields' to formset_for_model
    347     # an 'omit' argument would be very handy here
    348     try:
    349         del FormSet.form_class.base_fields[fk.name]
    350     except KeyError:
    351         pass
    352     FormSet.parent_model = parent_model
    353     FormSet.fk_name = fk.name
    354     FormSet.fk = fk
     360    FormSet.add_fk(parent_model, model, fk_name)
    355361    return FormSet
Back to Top