使用占位符和错误验证为 CreateView 和 UpdateView 制作自定义模板

Making a custom template for CreateView and UpdateView with placeholders and error validation

我在学习 Django 的同时制作了一个通用博客。

我有一个 ArticleCreateViewArticleUpdateView,我正在尝试制作一个两个视图都可以共享的自定义模板。 据我了解,CreateViewUpdateView 默认使用相同的模板 (article_form.html),这是我要修改的模板。

我的 models.py 中有以下内容:

class Article(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    # def __str__ ...
    # def get_absolute_url ...

在我的 views.py:

class ArticleCreateView(CreateView):
    model = Article
    fields = ['title', 'body']      
    template_name = 'article_form.html'


class ArticleCreateView(CreateView):
    model = Article
    fields = ['title', 'body']
    template_name = 'article_form.html'

在我的模板中包含以下内容 article_form.html 有效:

<form method='post'>
  {{ form.as_p }}
  <button>
    Publish
  </button>
</form>

不过我想让它更花哨,加载 CSS,简化版本是:

<form method='post'>
  {% csrf_token %}
  <fieldset class="fieldset-class">
    {{ form.title.errors }}
    <input
      class="form-class"
      type="text"
      placeholder="Article Title"
      name="{{ form.title.name }}"
      value="{{ form.title.value }}"
    />
  </fieldset>
  <fieldset class="form-group">
    {{ form.body.errors }}
    <textarea
      class="form-control"
      rows="8"
      placeholder="Article Body"
      name="{{ form.body.name }}"
    >{{ form.body.value }}</textarea>
  </fieldset>
</form>

我想要的是这样一种形式:

以上 html 执行以下操作:

将上面 html 中的 object.titleobject.body 替换为 form.title.valueform.body.value 会执行以下操作:

我已经阅读了文档的 Built-in template tags and filters, Rendering fields manually, Rendering form error messages, Looping over the form’s fields, and Attributes of BoundField,在 SO 和 GitHub 上寻找了类似的代码,阅读了 {{ form.as_p }} 呈现的源代码,但我没有找到简单的解决方案,尽管据说有常见用例。

我唯一能想到的就是到处推{% if %}语句在placeholdervalue之间进行选择,或者得到一些第三方库,比如crispy-forms, 但感觉应该存在一个更 pythonic 的解决方案。

一如既往,我在 SO 上发布问题后立即找到了答案。

内置模板过滤器default_if_none解决了问题:

    <input
      class="form-class"
      type="text"
      placeholder="Article Title"
      name="{{ form.title.name }}"
      value="{{ form.title.value|default_if_none:'' }}"
    />