djangodjango-modelswagtaildjango-modeladmin

Wagtail ModelAdmin > how to set initial data for an InlinePanel?


I have created a Planning and a Meeting model. I use Wagtail's ModelAdmin to administer them. Planning has a planning_panels which is an InlinePanel.

For other models I can set initial data using the form's __init__ method.
But I can't figure out how to implement this for the formsets used by the InlinePanel. Does anyone have any ideas? Here is the code:

class Planning(ClusterableModel):

    base_form_class = PlanningForm

    planning_panels = [
        InlinePanel(
            'planning_meetings',
            min_num = 2,
            max_num = 8,
            label = 'meetings'
        )
    )
    edit_handler = TabbedInterface([
        ObjectList(planning_panels, heading=_('meetings')),
    ])


class PlanningMeeting(models.Model):

    planning = ParentalKey(
        'cms.Planning',
        related_name='planning_meetings',
    )
    start = models.DateTimeField(
        'start'
    )
    finish = models.DateTimeField(
        'finish'
    )
    panels = [
        FieldPanel('start'),
        FieldPanel('finish')
    ]

    class Meta:
        verbose_name = 'Planned meeting'


class PlanningForm(WagtailAdminModelForm):

    class Meta:
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance')
        if not instance or not instance.pk:
            initial = kwargs.get('initial', {})
            initial.update({
                'some_fiel': 'some_value'
            })
            kwargs['initial'] = initial
        super().__init__(*args, **kwargs)


class CreatePlanningView(CreateView):

    pass


class PlanningAdmin(ModelAdmin):
    model = Planning
    create_view_class = CreatePlanningView

Solution

  • the wagtail's InlinePanel is uses django-modelcluster package. With that in mind, you can add initial data into wagtail create model admin by overriding the get_instance method from CreateView and then add the planning_meetings list.

    here is the code:

    class CreatePlanningView(CreateView):
        def get_instance(self):
          instance = super().get_instance()
    
          # add the initial inline panels here
          instance.planning_meetings = [
            PlanningMeeting(start=start, end=end),
            PlanningMeeting(start=start, end=end)
            # ... add more initial datas
          ]
    
          # dont forget to return the instance
          return instance
    
    

    The hint is from the django-modelcluster documentation https://github.com/wagtail/django-modelcluster