Django: Admin inline forms initial data for every instance

前端 未结 6 1527
名媛妹妹
名媛妹妹 2020-12-15 05:20

I\'ve been reading a lot but I don\'t seem to be able to figure out a solution to this.

I\'m writing an application in Django, I\'m still writing the admin side.

相关标签:
6条回答
  • 2020-12-15 05:52

    Here is my implementation, thanks to Steven for the idea.

    All in admin.py:

    class SecondaryModelInline(admin.ModelAdmin):
        model = SecondaryModel
        formset = SecondaryModelInlineFormSet
    
        def get_formset(self, request, obj=None, **kwargs):
            formset = super(SecondaryModelInline, self).get_formset(request, obj, **kwargs)
            formset.request = request
            return formset
    
        def get_extra(self, request, obj=None, **kwargs):
            extra = super(SecondaryModelInline, self).get_extra(request, obj, **kwargs)
            something = request.GET.get('something', None)
            if something:
                extra = ... figure out how much initial forms there are, from the request ...
            return extra
    

    Someplace before, also in admin.py, this:

    class SecondaryModelInlineFormSet(forms.models.BaseInlineFormSet):
        model = SecondaryModel
    
        def __init__(self, *args, **kwargs):
            super(SecondaryModelInlineFormSet, self).__init__(*args, **kwargs)            
            if self.request.GET.get('something', None):
                # build your list using self.request
                self.initial=[{'field_a': 'A', ...}, {}... ]
    
    0 讨论(0)
  • 2020-12-15 05:58

    Well, I wanted to comment on frnhr's answer, but did not have enough reputation, so:

    The answer worked for me, I just needed to loop through the forms in the formset and set the initial data for each of them:

    class SecondaryModelInlineFormSet(forms.models.BaseInlineFormSet):
        model = SecondaryModel
    
        def __init__(self, *args, **kwargs):
            super(SecondaryModelInlineFormSet, self).__init__(*args, **kwargs)            
            if self.request.GET.get('something', None):
                # build your list using self.request
                for form in self:
                    form.initial = {'field_a':'A',...} #This is what I changed
                self.initial=[{'field_a': 'A', ...}, {}... ]
    
    0 讨论(0)
  • 2020-12-15 06:00

    I realized that I solved the problem myself and hadn't answered here.

    What I finally did is to override the Environment class save_model method instead for using the admin forms.

    I'll explain a little bit better:

    I have an environment object and a server object. An environment has a number of servers that are linked to it via a foreign key into the server object. My goal was to populate the servers associated to an environment in the environment creation process. To be able to do that what I did was override the save_model method for the Environment object, do an obj.save() and AFTERWARDS create the Server objects that point to this environment, and then obj.save() again. Why afterwards? Because I can't relation a new created server with an environment that doesn't exist yet. Let me know if there is someone interested on he actual code.

    0 讨论(0)
  • 2020-12-15 06:03

    I haven't tried this but since the extra forms generated are essential Django Formsets, what you need to do is bind initial data to the formset which is explained in the docs here.

    I just read through the docs and it looks like you can define your own formset inside your inlineadmin and then as mentioned above, prepopulate the formset with data from your list. I think you could achieve that by placing the prepopulation code in your class' init method.

    I know this isn't a very elaborate explanation but I found the question interesting and looked up the docs and thought maybe I could point you in the right direction with what to try next.

    0 讨论(0)
  • 2020-12-15 06:09

    Not sure exactly why you want to do this, but perhaps you could create a modelformset:

    from django.forms.models import BaseModelFormSet
    class ServerFormSet(BaseModelFormSet):
        def __init__(self, *args, **kwargs):
            super(ServerFormSet, self).__init__(*args, **kwargs)
            self.initial = [{ 'name': 's1', }, {'name': 's2'},] # supply your list here
    

    and set this on your inline:

    class ServerInline(admin.TabularInline):
        form = ServerInlineAdminForm
        model = Server
        extra = 39
        formset = ServerFormSet
    

    I have not tried this out.

    See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.formset

    https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

    https://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset

    0 讨论(0)
  • 2020-12-15 06:15

    It worked for me in case of prepopulating user from request.user for StackedInline and TabularInline.

    def save_formset(self, request, form, formset, change):
        for form in formset.forms:
            form.instance.user = request.user
        formset.save()
    
    0 讨论(0)
提交回复
热议问题