Django

Code

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_Kral, 1 year ago)

version matching django @6158

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

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

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