Making a custom template for CreateView and UpdateView with placeholders and error validation
I'm making a generic blog while learning Django.
I have an ArticleCreateView
and ArticleUpdateView
, and I am trying to make a custom template that both views would share.
From what I understand, CreateView
and UpdateView
use the same template by default (article_form.html
), which is the template I'm trying to modify.
I have the following in my models.py:
class Article(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
# def __str__ ...
# def get_absolute_url ...
In my 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'
Having the following in my template article_form.html works:
<form method='post'>
{{ form.as_p }}
<button>
Publish
</button>
</form>
I want to make it more fancy though, with loads of CSS, and a simplified version is:
<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>
What I want is a form that:
- has placeholders in empty fields (instead of labels)
- has model-based error validation (
max_length
is respected and both fields arerequired
without me having to specify it) - doesn't erase the entered values upon submitting
The above html does the following:
- submitting with empty fields will raise the errors, and any entered values will be persisted (good)
- empty fields have
None
instead of placeholders (issue)
Substituting object.title
and object.body
to form.title.value
and form.body.value
in the above html does the following:
- submitting with empty fields will raise the errors, but also erase the entered values (issue)
- empty fields have the right placeholders (good)
I have read the documentation's Built-in template tags and filters, Rendering fields manually, Rendering form error messages, Looping over the form’s fields, and Attributes of BoundField, looked for similar code on SO and GitHub, read the source rendered by {{ form.as_p }}
, but I find no simple solution despite having a supposedly common usecase.
The only thing I can think of is to shove {% if %}
statements everywhere to choose between placeholder
and value
, or to get some third-party lib like crispy-forms, but it feels like a more pythonic solution should exist.
As always, I found the answer immediately after posting the question on SO.
The built-in template filter default_if_none
solves the issue:
<input
class="form-class"
type="text"
placeholder="Article Title"
name="{{ form.title.name }}"
value="{{ form.title.value|default_if_none:'' }}"
/>