【问题标题】:Django forms not rendering on production server - work fine locally with testserver, and unit tests pass on production serverDjango 表单未在生产服务器上呈现 - 在本地与 testserver 一起正常工作,并且单元测试在生产服务器上通过
【发布时间】:2016-08-24 12:23:09
【问题描述】:

这可能是我作为开发人员在短时间内遇到的最奇怪的错误。我有一个可以在本地机器上完美呈现的表单,但完全相同的代码无法在服务器上呈现。

我有一个表格,看起来像这样:

没什么花哨的,只有几个输入字段和一个提交按钮。

我是如何创建它的?那么首先有一个表格:

from django import forms
from django.forms.extras.widgets import SelectDateWidget
from blog.models import BlogPost

EMPTY_FIELD_ERROR = "You cannot submit a blog post with no %s"


class DateInput(forms.DateInput):
    input_type = 'date'



class PlainTextarea(forms.Textarea):

    def build_attrs(self, extra_attrs=None, **kwargs):
        attrs = super(PlainTextarea, self).build_attrs(extra_attrs, **kwargs)
        if "cols" in attrs: del attrs["cols"]
        if "rows" in attrs: del attrs["rows"]
        return attrs



class BlogPostForm(forms.models.ModelForm):


    class Meta:
        model = BlogPost
        fields = ("title", "date", "body", "visible")
        widgets = {
         "title": forms.fields.TextInput(attrs={
          "class": "pure-u-1-1 pure-u-md-19-24"
         }),
         "date": DateInput(),
         "body": PlainTextarea(attrs={
          "class": "pure-u-1-1 pure-u-md-19-24"
         }),
         "visible": forms.CheckboxInput(attrs={
          "class": "pure-u-1-24"
         })
        }
        error_messages = {
         "title": {"required": EMPTY_FIELD_ERROR % "title"},
         "date": {"required": EMPTY_FIELD_ERROR % "date"},
         "body": {"required": EMPTY_FIELD_ERROR % "body"}
        }

在 new_post 视图中,如果检测到请求是 GET 请求,我就简单地创建这个表单的实例,并将其传递给 new_post 模板:

def new_post_page(request):
    if request.method == "POST":
        form = BlogPostForm(request.POST)
        if form.is_valid():
            BlogPost.objects.create(
             title=request.POST["title"].strip(),
             date=datetime.datetime.strptime(
              request.POST["date"], "%Y-%m-%d"
             ).date(),
             body=request.POST["body"].strip(),
             visible=request.POST.get("visible") is not None
            )
            return redirect("/")
        else:
            return render(request, "new_post.html", {"form": form})
    form = BlogPostForm()
    return render(request, "new_post.html", {"form": form})

这是模板的一部分:

<form method="POST" class="pure-form pure-form-aligned">
  <div class="pure-g">
    <div class="pure-u-1-1 formrow">
      <label for="{{ form.title.id_for_label }}" class="pure-u-1-1 pure-u-md-4-24">Title:</label>
      {{ form.title }}
      {% if form.title.errors %}
      <div class="error">
        {{ form.title.errors }}
      </div>
      {% endif %}
    </div>
    <div class="pure-u-1-1 formrow">
      <label for="{{ form.date.id_for_label }}" class="pure-u-1-1 pure-u-md-4-24">Date:</label>
      {{ form.date }}
      {% if form.date.errors %}
      <div class="error">
        {{ form.date.errors }}
      </div>
      {% endif %}
    </div>

这一切在我自己的机器上运行良好(MacBook、El Capitain、Python3、Django 1.8.4),但是当我将代码部署到服务器时,我得到了这个:

检查 HTML 显示 {{form.title}} 标记尚未呈现。但一切都是一样的!好吧,大部分都是。显然,服务器上的某些设置是不同的,例如 Debug 设置为 False。我还在服务器上使用 postgres 数据库,在本地使用 SQLite 数据库。

为了让事情变得更加令人抓狂,我进行了单元测试,包括 new_page 视图正在呈现表单的测试——它们在服务器上传递!我什至在服务器上启动了一个 Django shell,手动将请求传递给 new_page 视图,打印了 HTML,输入的 HTML 就在那里

一些可能有用的信息:

  • 服务器使用nginx,向gunicorn发送请求。操作系统是 Ubuntu 14.04。
  • 在我将它连接到 Django 表单之前,当它全部是 HTML 时,表单呈现得非常好
  • 我已应用所有迁移 - 没有要应用的新迁移,但每当我部署时都会自动进行迁移。

请帮助这个 Django 新手?

更新

我尝试使用 django 测试服务器代替 gunicorn,并且可以正确呈现表单,所以可能是 gunicorn 的问题?

【问题讨论】:

  • 您可以尝试this answer中建议的步骤,看看渲染表单是否有错误?
  • 嗨 - 谢谢,但这并不能解决问题。当我在 shell 中使用 as_p() 时,表单呈现得很好。我已经更新了我的问题以报告在生产服务器上使用 django 测试服务器而不是 gunicorn 确实可以解决问题,所以看起来 gunicorn 是问题所在。不过我对此知之甚少。
  • 您可以通过form = BlogPostForm(request.POST or None) 简化您的视图代码并消除if request.method == "POST": 和冗余的默认渲染分支
  • 另外,可以说您在 BlogPost.objects.create 部分中所做的值的规范化应该是模型表单代码的一部分,然后您可以简单地执行 form.save() 来创建新的博客文章
  • 你不见了{% csrf_token %}

标签: python django forms django-forms django-templates


【解决方案1】:

以防另一个可怜的灵魂落在这里。检查您的包(pip freeze)在本地和服务器上是否相同。我在本地有 django-filter==0.15.0,在服务器上有 django-filter==0.10.0,这导致了这个确切的问题,没有引发任何错误。

【讨论】:

    【解决方案2】:

    所以,我已经解决了这个问题。不幸的是,我不完全确定如何。

    正如我在更新中提到的,关闭 gunicorn 并改用 django 测试服务器解决了这个问题。我关闭了测试服务器并再次启动了 gunicorn,然后......表单仍然正确呈现。

    我的怀疑是重新启动 gunicorn 就足够了。我不知道为什么,或者这绝对是解决它的原因。哦,好吧。

    【讨论】:

      【解决方案3】:

      我在将 django 项目部署到 AWS EC2 时遇到了同样的问题。

      如果您已遵循 Nginx gunicorn 和 Django 教程,您最好的选择是重启 EC2,然后重启 gunicorn 服务器。这解决了我的问题。

      【讨论】:

        【解决方案4】:

        您应该在每次部署时重新启动您的网络服务器 - 这将确保您正在为您的应用运行最新的代码。这是非常具有欺骗性的,因为它会正确提取 html 模板,但不会运行呈现模板内容的代码(这就是为什么您看到的是硬编码的标签,而不是动态呈现的文本输入)。

        我在 Ubuntu 上使用 Apache,当我通宵调试某些东西时,这让我时不时地……部署新代码时总是重新启动服务器:

        sudo service apache2 restart

        【讨论】:

          猜你喜欢
          • 2011-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 2016-11-05
          • 1970-01-01
          相关资源
          最近更新 更多