Django

Code

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

File newforms-admin-6426-generic-edit-inline.patch, 9.4 kB (added by Honza_Kral, 1 year ago)

Matching django version 6426

  • a/django/contrib/admin/options.py

    old new  
    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 
     
    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.""" 
     
    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: 
  • a/django/contrib/contenttypes/generic.py

    old new  
    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) 
  • a/django/newforms/models.py

    old new  
    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): 
     
    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