Search code examples
pythondjangodjango-formsdjango-cms

How to integrate a Django app with multiple forms in Django CMS as plugin?


I followed this tutorial to integrate my Django app into my Django CMS website.

My app Sale has two models, OrderModel() and CustomerModel(), that both are used in forms.py to pass some fields to a form, like so:

class CustomerForm(forms.ModelForm):

    class Meta:
        model = CustomerModel
        fields = ['firstname', 'surname', 'company', 'email',]

class OrderForm(forms.ModelForm):

    class Meta:
        model = OrderModel
        fields = ['product', 'delivery_date',]

As described in the tutorial, in models.py I generate the SalePluginModel and in cms_plugins.py, I specify the SalePluginPublisher plugin class, which is responsible for providing django CMS with the necessary information to render my app, like so in models.py:

class SalePluginModel(CMSPlugin):

    title = models.CharField(u'title',
        blank=True,
        help_text=u'Optional. Title of the widget.',
        max_length=64,
    )

and so in cms_plugins.py:

class SalePluginPublisher(CMSPluginBase):
    model = SalePluginModel  # model where plugin data are saved
    module = _("Sale")
    name = _("Sale Plugin")  # name of the plugin in the interface
    render_template = "sale/sale_plugin.html"
    form = '' # How to pass multiple model forms here? 

Now, the problem is, that only one form class can be passed to the CMSPluginBase as attribute. Is there a possibility to include both form classes in the SalePluginPublisher or in general, how can I integrate my app with two models and forms in the Django CMS? Thank you very much for your help!


Solution

  • So to clarify, you'd like to pass two forms to the plugin? If so, you can do the following:

    class SalePluginPublisher(CMSPluginBase):
        model = SalePluginModel  # model where plugin data are saved
        module = _("Sale")
        name = _("Sale Plugin")  # name of the plugin in the interface
        render_template = "sale/sale_plugin.html"
    
        def render(self, context, instance, placeholder):
            context = super().render(context, instance, placeholder)
            context['customer_form'] = CustomerForm()
            context['order_form'] = OrderForm()
            return context
    

    You can handle the POST responses in the render function too if you don't have a dedicated POST url. You just need to access the request object, e.g. self.request.POST.

    Edit:

    The above works with Python 3, to use with Python 2 you need to change the first line of the render function to:

    context = super(SalePluginPublisher, self).render(context, instance, placeholder)
    ...