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

File newforms-admin-5519-generic-edit-inline.patch, 7.8 KB (added by Honza Král <Honza.Kral@…>, 17 years ago)

rough version of the patch

  • django/contrib/admin/options.py

     
    611612    def get_inline_formsets(self):
    612613        inline_formset_classes = []
    613614        for opts in self.inlines:
    614             inline = inline_formset(self.model, opts.model, formfield_callback=opts.formfield_for_dbfield, fields=opts.fields, extra=opts.extra)
     615            inline = inline_formset(
     616                        self.model,
     617                        opts.model,
     618                        formfield_callback=opts.formfield_for_dbfield,
     619                        fields=opts.fields,
     620                        extra=opts.extra,
     621                        fk_name=opts.name,
     622                        formset=opts.formset
     623                    )
    615624            inline_formset_classes.append(inline)
    616625        return inline_formset_classes
    617626
  • django/contrib/contenttypes/generic.py

    -    def __init__(self, model, name=None, extra=3, fields=None, template=None, raw_id_fields=None):
    +    def __init__(self, model, name=None, extra=3, fields=None, template=None, raw_id_fields=None, formset=None):
             self.model = model
             self.opts = model._meta
             self.name = name
    @@ -634,6 +645,7 @@
             self.verbose_name_plural = model._meta.verbose_name_plural
             self.prepopulated_fields = {}
             self.raw_id_fields = raw_id_fields or ()
    +        self.formset = formset
     
     class StackedInline(InlineModelAdmin):
         default_template = 'admin/edit_inline_stacked.html'
     
    258258        self.multiple = True
    259259        assert not (self.raw_id_admin and self.filter_interface), \
    260260            "Generic relations may not use both raw_id_admin and filter_interface"
     261
     262from django.newforms.models import InlineFormset, save_instance
     263class GenericInlineFormset(InlineFormset):
     264
     265    @classmethod
     266    def add_fk( cls, parent_model, model, fk_name ):
     267        assert ':' in fk_name, "Supply valid content_type:object_id as fk_name."
     268
     269        opts = model._meta
     270        ct_field_name, id_field_name = fk_name.split( ':' )
     271        ct = opts.get_field( ct_field_name )
     272        obj_id = opts.get_field( id_field_name )
     273        # HACK: remove the ForeignKey to the parent from every form
     274        # This should be done a line above before we pass 'fields' to formset_for_model
     275        # an 'omit' argument would be very handy here
     276        try:
     277            del cls.form_class.base_fields[ct.name]
     278            del cls.form_class.base_fields[obj_id.name]
     279        except KeyError:
     280            pass
     281
     282        cls.parent_model = parent_model
     283        cls.model = model
     284        cls.ct_field_name = ct_field_name
     285        cls.id_field_name = id_field_name
     286        cls.ct = ct
     287        cls.obj_id = obj_id
     288
     289    def get_inline_objects( self ):
     290        # This import is done here to avoid circular import importing this module
     291        from django.contrib.contenttypes.models import ContentType
     292        if self.instance is None:
     293            return []
     294        return self.model._default_manager.filter( **{
     295                self.ct_field_name : ContentType.objects.get_for_model( self.instance ),
     296                self.id_field_name : self.instance._get_pk_val()
     297            })
     298
     299    def save_new(self, form, commit=True):
     300        # This import is done here to avoid circular import importing this module
     301        from django.contrib.contenttypes.models import ContentType
     302        kwargs = {
     303            self.ct.get_attname(): ContentType.objects.get_for_model( self.instance ).id,
     304            self.obj_id.get_attname(): self.instance._get_pk_val(),
     305        }
     306        new_obj = self.model(**kwargs)
     307        return save_instance(form, new_obj, commit=commit)
     308
  • django/newforms/models.py

     
    282282        from django.db.models.fields.related import RelatedObject
    283283        self.instance = instance
    284284        # is there a better way to get the object descriptor?
    285         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
    286         super(InlineFormset, self).__init__(data, instances=self.get_inline_objects(), prefix=self.rel_name)
     285        #self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
     286        super(InlineFormset, self).__init__(data, instances=self.get_inline_objects(), prefix='aaaa' ) #prefix=self.rel_name)
    287287
     288    @classmethod
     289    def add_fk( cls, parent_model, model, fk_name ):
     290        opts = model._meta
     291        # figure out what the ForeignKey from model to parent_model is
     292        if fk_name is None:
     293            fks_to_parent = [f for f in opts.fields if isinstance(f, ForeignKey) and f.rel.to == parent_model]
     294            if len(fks_to_parent) == 1:
     295                fk = fks_to_parent[0]
     296            elif len(fks_to_parent) == 0:
     297                raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
     298            else:
     299                raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
     300        else:
     301            fk = opts.get_field( fk_name )
     302        # HACK: remove the ForeignKey to the parent from every form
     303        # This should be done a line above before we pass 'fields' to formset_for_model
     304        # an 'omit' argument would be very handy here
     305        try:
     306            del FormSet.form_class.base_fields[fk.name]
     307        except KeyError:
     308            pass
     309
     310        cls.parent_model = parent_model
     311        cls.fk_name = fk.name
     312        cls.fk = fk
     313
    288314    def get_inline_objects(self):
    289315        if self.instance is None:
    290316            return []
     
    295321        new_obj = self.model(**kwargs)
    296322        return save_instance(form, new_obj, commit=commit)
    297323
    298 def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, formfield_callback=lambda f: f.formfield()):
     324def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, formfield_callback=lambda f: f.formfield(), formset=None):
    299325    """
    300326    Returns an ``InlineFormset`` for the given kwargs.
    301327   
     
    303329    to ``parent_model``.
    304330    """
    305331    from django.db.models import ForeignKey
    306     opts = model._meta
    307     # figure out what the ForeignKey from model to parent_model is
    308     if fk_name is None:
    309         fks_to_parent = [f for f in opts.fields if isinstance(f, ForeignKey) and f.rel.to == parent_model]
    310         if len(fks_to_parent) == 1:
    311             fk = fks_to_parent[0]
    312         elif len(fks_to_parent) == 0:
    313             raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
    314         else:
    315             raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
    316332    # let the formset handle object deletion by default
    317     FormSet = formset_for_model(model, formset=InlineFormset, fields=fields, formfield_callback=formfield_callback, extra=extra, deletable=True)
    318     # HACK: remove the ForeignKey to the parent from every form
    319     # This should be done a line above before we pass 'fields' to formset_for_model
    320     # an 'omit' argument would be very handy here
    321     try:
    322         del FormSet.form_class.base_fields[fk.name]
    323     except KeyError:
    324         pass
    325     FormSet.parent_model = parent_model
    326     FormSet.fk_name = fk.name
    327     FormSet.fk = fk
     333    FormSet = formset_for_model(model, formset=formset or InlineFormset, fields=fields, formfield_callback=formfield_callback, extra=extra, deletable=True)
     334    FormSet.add_fk( parent_model, model, fk_name)
    328335    return FormSet
Back to Top