how to use forms in django-cms? how to use forms in django-cms? django django

how to use forms in django-cms?


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.


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'm new to django-cms too, but the way ojii described in their answer seems like the most reasonable:

  • Make a CMSPlugin as described above 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.

However for me this only a partial solution because I don't only want to redirect back to the cms page containing the plugin in the case of success but also in the case of form errors which need to be displayed. The redirecting part is not the problem (I just redirect back to request.META["HTTP_REFERER"]), but the part of handing over the form (errors) to the cms page containing the plugin is tricky. The only answer I found for this: I use a session (Writing the form into the session in the static view, and then deleting it again in the plugin's render method). Not the nicest way, but it works. (There would be better ways, if the cms plugins configuration would support some way to redirect instead of rendering, but apparently there is no such option: see http://groups.google.com/group/django-cms/browse_thread/thread/79ab6080c80bbcb5 )