将 Django 表单传递给模板标签

Posted

技术标签:

【中文标题】将 Django 表单传递给模板标签【英文标题】:Passing a Django form to a template tag 【发布时间】:2017-03-02 23:23:03 【问题描述】:

我正在尝试在我的 Wagtail 网站的每个页面上的 jQuery 滑出框中呈现一个 Django 表单。我创建了一个模板标签,当前正在呈现该框,但该表单未显示。我在想我错误地传递了表单变量。我的模板标记文件如下所示:

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 看起来像这样:

% 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>

我的表单如下所示:

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)

我用来尝试在主 base.html 中呈现它的模板标签是% book_a_demo request %

知道我做错了什么吗?我没有收到任何错误;它只是没有出现。我已经坚持了几个小时,这让我发疯了。

【问题讨论】:

【参考方案1】:

当请求不是 POST 或者 is_valid() 为 false 时返回什么?我通常使用这样的模式(注意最后的变化):

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')
    else:
        demo_form = form()

    return render(request, 'demo_form.html', 'form': demo_form)

【讨论】:

【参考方案2】:

使用inclusion_tag 时,您不应自己致电render。您应该返回上下文字典(例如:return 'form': form) - 然后 Django 将负责呈现您在 @register.inclusion_tag('demo_form.html') 声明中命名的模板。

我建议不要尝试处理标记中的if request.method == 'POST': 逻辑,因为任何时候您网站上的任何页面响应 POST 请求而呈现时都会触发 - 无论 POST 请求是否有任何事情要做与您的演示表格。相反,您应该设置一个 Django 视图来处理这些表单提交,并将该视图的 URL 放在表单的 action 属性中。

【讨论】:

以上是关于将 Django 表单传递给模板标签的主要内容,如果未能解决你的问题,请参考以下文章

从 Django HTML 表单中检索数据并将其传递给 MySQL 数据库

将Django Choices表单字段的详细名称传递给查看上下文

无法从继承的模板访问 django 表单

Django:在带有前缀的模板中显示表单名称

python Django:将表单视图中的变量传递给表单

将实例传递给 Django 表单集