Quick n' dirty:
I've found that the following works well: instead of using the field directly, I wrap them in a jinja macro:
{% macro render_field(field) %}
<label>
<span>{{ _field.label.text }} </span>
{{ field(id=False, **kwargs) }}
</label>
{% endmacro %}
which can be used like this:
{% from "_formhelpers.html" import render_field %}
{{ render_field(form.name) }}
The trick here is to pass id=False
when rendering the field.
using the meta object:
_Auto = object()
class NoIdAttributeMeta(DefaultMeta):
"""
Surpresses rendering the `id' attribute.
"""
def bind_field(self, form, unbound_field, options):
"""
Raises TypeError in case 'id' is given as a positional arg when constructing a field.
If this happens, make this code smarter or pass `id' as a keyword arg.
"""
# we check `id' at rendering time and if it is still _Auto, do not render it
unbound_field.kwargs.setdefault('id', _Auto)
return super().bind_field(form, unbound_field, options)
def render_field(self, field, render_kw):
if field.id is _Auto:
field.id = False
return super().render_field(field, render_kw)
class MyForm(flask_wtf.Form):
Meta = NoIdAttributeMeta
or be pragmatic:
You could also add a different prefix to each instance of your form and therefore you'd have unique ids:
my_form = MyForm(prefix="form1")
pass