Passing a Django form to a template tag

django, templatetags, wagtail

Solution

When using `inclusion_tag`, you shouldn't call `render` yourself. You should return the context dictionary (for example: `return {'form': form}`) - Django will then take care of rendering the template you named in the `@register.inclusion_tag('demo_form.html')` declaration.

I would advise against trying to handle the `if request.method == 'POST':` logic within the tag, as that will be triggered any time any page on your site is rendered in response to a POST request - regardless of whether the POST request had anything to do with your DemoForm. Instead, you should set up a Django view to handle those form submissions, and put the URL to that view in the form's `action` attribute.

Problem

I'm trying to render a Django form on every page of my Wagtail site in a jQuery slideout box. I've created a template tag that is currently rendering the box, but the form is not showing up. I'm thinking that I'm incorrectly passing the form variable. My template tag file looks like this: ``` from django import template from django.shortcuts import render, redirect from django.template.loader import get_template from django.core.mail import EmailMessage from django.template import Context from .forms import DemoForm register = template.Library() @register.inclusion_tag('demo_form.html') def book_a_demo(request): form = DemoForm if request.method == 'POST': demo_form = form(data=request.POST) if demo_form.is_valid(): contact_name = request.POST.get('name', '') company_name = request.POST.get('company', '') contact_email = request.POST.get('email', '') contact_phone = request.POST.get('phone', '') # Email the profile with the # contact information template = get_template('contact_template.txt') context = Context({ 'contact_name': contact_name, 'company_name': company_name, 'contact_email': contact_email, 'contact_phone': contact_phone, }) content = template.render(context) email = EmailMessage( "Request to Book a Demo", content, "domain" +'', ['example@email.com'], headers = {'Reply-To': contact_email } ) email.send() return render(request, 'demo_form_landing.html') return render(request, 'demo_form.html', {'form': form}) ``` demo_form.html looks like this: ``` {% load static %} <div id="feedback"> <div id="feedback-tab">Book a Demo</div> <div id="feedback-form" style='display:block;' class="col-xs-4 col-md-4 panel panel-default"> <form role="form" action="" method="post" class="form panel-body"> {% csrf_token %} {{ form.as_p }} <button class="btn btn-primary pull-right" type="submit">Send</button> </form> </div> </div> ``` My form looks like this: ``` from django import forms class DemoForm(forms.Form): name = forms.CharField(initial='Your Name', max_length=100) company = forms.CharField(initial='Company Name', max_length=100) email = forms.EmailField(initial='Email') phone = forms.CharField(initial='Phone Number', max_length=100) ``` The template tag I'm using to try to render it in the main base.html is `{% book_a_demo request %}` Any idea what I'm doing wrong? I don't get any errors; it just doesn't appear. I've been stuck on this for hours and it's driving me crazy.

Original source