Django admin dynamically sets initial change data

I am implementing m2m communication through an intermediate model using the default m2m widget. I have models Person

and Project

related to using the model Membership

.

So far I have managed to display the default m2m widget on the change form Person

and instantiate the intermediate model correctly, but my problem is populating the widget on change Person

.

This is the form class I am using with PersonAdmin

:

class PersonForm(forms.ModelForm):
    projects = forms.ModelMultipleChoiceField(models.Project.objects.all(),
                                              widget=widgets.FilteredSelectMultiple(
                                                  verbose_name="Projects",
                                                  is_stacked=False,
                                                  attrs={'rows':'10'}))
    projects.required = False
    class Meta:
        model = models.Person
        fields = ['name', 'last_name', 'personal_id_number',
                  'personal_id_type', 'administrative_viability',
                  'observations']

    def save(self, commit=True):
        ret = super(PersonForm, self).save(commit)
        for p in self.cleaned_data['projects']:
            models.Membership.objects.create(person=self.instance, project=p)
        return ret

      

And myself PersonAdmin

:

class PersonAdmin(admin.ModelAdmin):
    form = PersonForm

    def get_changeform_initial_data(self, request):
        initial = super(PersonAdmin, self).get_changeform_initial_data(request)
        initial['projects'] = models.Person.get(pk=initial['person']).project_set.all()
        return initial

      

I tried to set an initial value projects

in a method get_changeform_initial_data

like this, but it doesn't work. All in all it looks like this is being ignored, as if I am not overriding it properly.

Any help would be greatly appreciated!

+4


source to share


2 answers


This question gave me the idea to override the method of __init__

mine PersonForm

:

def __init__(self, *args, **kwargs):
    if 'instance' in kwargs:
        person = kwargs['instance']
        initial = {'projects': person.project_set.all()}
        kwargs['initial'] = initial
    super(PersonForm, self).__init__(*args, **kwargs)

      



I still don't know why the override get_changeform_initial_data

didn't work.

+4


source


get_changeform_initial_data

only called if it is not a change. I know it doesn't make sense. I suspect this is a bug.

See django/contrib/admin/options.py

from line 1573, which is the only call to this method in all of Django:



            if add:
                initial = self.get_changeform_initial_data(request)
                form = ModelForm(initial=initial)
                formsets, inline_instances = self._create_formsets(request, form.instance, change=False)
            else:
                form = ModelForm(instance=obj)
                formsets, inline_instances = self._create_formsets(request, obj, change=True)

      

0


source







All Articles