how to use forms in django-cms?

Assuming your product application works as expected without Django CMS, what you'd next want to do is create your own plugin to show the form. The plugin would render your form, which you've already defined in your own application using a plugin template that you've created.

This plugin for a contact form allows the contact form to be inserted into the page template anywhere a placeholder will allow it.

class ContactPlugin(CMSPluginBase):
    """Enables latest event to be rendered in CMS"""

    model = CMSPlugin
    name = "Form: Contact"
    render_template = "contact_form/contact_plugin.html"

    def render(self, context, instance, placeholder):
        request = context['request']
        context.update({
            'instance': instance,
            'placeholder': placeholder,
            'form': ContactForm(request=request),
        })
        return context

The template would include all the HTML and Django template language necessary to render the form.

This other contact form plugin shows another example of how to do it. Instead of rendering the form it just updates the context. The upside is that you don't have to create a separate template, but the downside is that you lose some of the modularity of having a plugin. This depends on the page template rendering the form.

class ContactPlugin(CMSPluginBase):
    model = Contact
    name = _("Contact Form")
    render_template = "contact.html"

    def render(self, context, instance, placeholder):
        request = context['request']

         if request.method == "POST":
            form = ContactForm(request.POST)
            if form.is_valid():
                form.send(instance.site_email)
                context.update( {
                    'contact': instance,
                    })
            return context
        else:
            form = ContactForm()

            context.update({
            'contact': instance,
            'form': form,
            })
            return context

In either case you still have to define the view to accept the form submission, which means you'll need to create a view outside of the CMS acknowledging receipt of the form with its own template, redirecting the user back to the referring page, and/or accepting an AJAX request.


I've recently ran across django-form-designer

It's quite nice and lets you design forms in a wysiwyg manner. Works for stand alone django applications and has an additional plugin for Django-CMS. One note: you have to follow the standalone instructions in addition to the Django-CMS instructions for installation.

From the github description:

Key features:

  • Design contact forms, search forms etc from the Django admin, without writing any code
  • Form data can be logged and CSV-exported, sent via e-mail, or forwarded to any web address
  • Integration with Django CMS: Add forms to any page
  • Use drag & drop to change the position of your form fields
  • Fully collapsible admin interface for better overview over your form
  • Implements many form fields included with Django (TextField, EmailField, DateField etc)
  • Validation rules as supplied by Django are fully configurable (maximum length, regular expression etc)
  • Customizable messages and labels
  • Supports POST and GET forms

Actually the solution proposed by bennylope is not the preferred way to do it, since using request.POST in a plugin can have very bad side effects (eg: what if the same plugin is twice on a page? Or what if there's multiple plugins waiting for POST data on the same page? Those plugins would confuse each other when there's a POST to that page).

So the preferred way is:

  • Make a CMSPlugin as described by bennylope to render the form.
  • Make the form post to a statically hooked view (or a apphooked view), if the POST is successful, redirect to the page again if you want.