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

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

version matching django @6158

  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 433be1e..4c7a6bd 100644
    a b class InlineModelAdmin(BaseModelAdmin):  
    689689    template = None
    690690    verbose_name = None
    691691    verbose_name_plural = None
     692    formset = None
    692693
    693694    def __init__(self, parent_model, admin_site):
    694695        self.admin_site = admin_site
    class InlineModelAdmin(BaseModelAdmin):  
    706707            fields = flatten_fieldsets(self.declared_fieldsets)
    707708        else:
    708709            fields = None
    709         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)
     710        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields,
     711                    formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset)
    710712
    711713    def formset_change(self, request, obj):
    712714        """Returns an InlineFormSet class for use in admin change views."""
    class InlineModelAdmin(BaseModelAdmin):  
    714716            fields = flatten_fieldsets(self.declared_fieldsets)
    715717        else:
    716718            fields = None
    717         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)
     719        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields,
     720                    formfield_callback=self.formfield_for_dbfield, extra=self.extra, formset=self.formset)
    718721
    719722    def fieldsets_add(self, request):
    720723        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..ddf3bd1 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
     264
     265
     266from django.newforms.models import InlineFormset, save_instance
     267class GenericInlineFormset(InlineFormset):
     268
     269    @classmethod
     270    def add_fk(cls, parent_model, model, fk_name):
     271        from django.template.defaultfilters import slugify
     272        assert ':' in fk_name, "Supply valid content_type:object_id as fk_name."
     273
     274        opts = model._meta
     275        ct_field_name, id_field_name = fk_name.split(':')
     276        ct = opts.get_field( ct_field_name )
     277        obj_id = opts.get_field( id_field_name )
     278        # HACK: remove the ForeignKey to the parent from every form
     279        # This should be done a line above before we pass 'fields' to formset_for_model
     280        # an 'omit' argument would be very handy here
     281        try:
     282            del cls.form_class.base_fields[ct.name]
     283            del cls.form_class.base_fields[obj_id.name]
     284        except KeyError:
     285            pass
     286
     287        cls.parent_model = parent_model
     288        cls.model = model
     289        cls.ct_field_name = ct_field_name
     290        cls.id_field_name = id_field_name
     291        cls.ct = ct
     292        cls.obj_id = obj_id
     293        cls.rel_name = slugify(fk_name)
     294
     295    def get_inline_objects(self):
     296        # This import is done here to avoid circular import importing this module
     297        from django.contrib.contenttypes.models import ContentType
     298        if self.instance is None:
     299            return []
     300        return self.model._default_manager.filter( **{
     301                self.ct_field_name : ContentType.objects.get_for_model(self.instance),
     302                self.id_field_name : self.instance._get_pk_val()
     303            })
     304
     305    def save_new(self, form, commit=True):
     306        # This import is done here to avoid circular import importing this module
     307        from django.contrib.contenttypes.models import ContentType
     308        kwargs = {
     309            self.ct.get_attname(): ContentType.objects.get_for_model(self.instance).id,
     310            self.obj_id.get_attname(): self.instance._get_pk_val(),
     311        }
     312        new_obj = self.model(**kwargs)
     313        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 bfbc2c2..034f3aa 100644
    a b def formset_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formf  
    289289class InlineFormset(BaseModelFormSet):
    290290    """A formset for child objects related to a parent."""
    291291    def __init__(self, instance=None, data=None, files=None):
    292         from django.db.models.fields.related import RelatedObject
    293292        self.instance = instance
    294293        # is there a better way to get the object descriptor?
    295         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
    296294        super(InlineFormset, self).__init__(data, files, instances=self.get_inline_objects(), prefix=self.rel_name)
     295 
     296    @classmethod
     297    def add_fk(cls, parent_model, model, fk_name):
     298        from django.db.models import ForeignKey
     299        from django.db.models.fields.related import RelatedObject
     300        opts = model._meta
     301        # figure out what the ForeignKey from model to parent_model is
     302        if fk_name is None:
     303            fks_to_parent = [f for f in opts.fields if isinstance(f, ForeignKey) and f.rel.to == parent_model]
     304            if len(fks_to_parent) == 1:
     305                fk = fks_to_parent[0]
     306            elif len(fks_to_parent) == 0:
     307                raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
     308            else:
     309                raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
     310        else:
     311            fk = opts.get_field( fk_name )
     312        # HACK: remove the ForeignKey to the parent from every form
     313        # This should be done a line above before we pass 'fields' to formset_for_model
     314        # an 'omit' argument would be very handy here
     315        try:
     316            del cls.form_class.base_fields[fk.name]
     317        except KeyError:
     318            pass
     319
     320        cls.parent_model = parent_model
     321        cls.fk_name = fk.name
     322        cls.rel_name = RelatedObject(fk.rel.to, model, fk).get_accessor_name()
     323        cls.fk = fk
    297324
    298325    def get_inline_objects(self):
    299326        if self.instance is None:
    class InlineFormset(BaseModelFormSet):  
    305332        new_obj = self.model(**kwargs)
    306333        return save_instance(form, new_obj, commit=commit)
    307334
    308 def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield()):
     335def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False,
     336                    deletable=True, formfield_callback=lambda f: f.formfield(), formset=None):
    309337    """
    310338    Returns an ``InlineFormset`` for the given kwargs.
    311339   
    312340    You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
    313341    to ``parent_model``.
    314342    """
    315     from django.db.models import ForeignKey
    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))
    326343    # let the formset handle object deletion by default
    327     FormSet = formset_for_model(model, formset=InlineFormset, fields=fields,
    328                                 formfield_callback=formfield_callback, 
    329                                 extra=extra, orderable=orderable, 
     344    FormSet = formset_for_model(model, formset=formset or InlineFormset, fields=fields,
     345                                formfield_callback=formfield_callback,
     346                                extra=extra, orderable=orderable,
    330347                                deletable=deletable)
    331     # HACK: remove the ForeignKey to the parent from every form
    332     # This should be done a line above before we pass 'fields' to formset_for_model
    333     # an 'omit' argument would be very handy here
    334     try:
    335         del FormSet.form_class.base_fields[fk.name]
    336     except KeyError:
    337         pass
    338     FormSet.parent_model = parent_model
    339     FormSet.fk_name = fk.name
    340     FormSet.fk = fk
     348    FormSet.add_fk(parent_model, model, fk_name)
    341349    return FormSet
Back to Top