In my flask application I have to draw a form multiple times on the same page. This leads to the problem where I have multiple input fields with the same id on the page. E.g.:
class ChannelForm(flask_wtf.Form):
name = StringField('name')
together with this template:
<form>
{{ form.name }}
</form>
...
<form>
{{ form.name }}
</form>
lead to two input elements with the same id:
<input id="name" name="name" value="" type="text">
Is there an official way to disable adding the id attribute?
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
I think you can pass a custom id to the field constructor like this:
<form>
{{ form.name(id_='yourId') }}
</form>
...
<form>
{{ form.name(id_='yourId2') }}
</form>
You don't need id=False because you already can set id when you call render_field()
{% macro render_field(_field) %}
<label>
<span>{{ _field.label.text }} </span>
{{ _field(**kwargs) }}
</label>
{% endmacro %}
Usage:
{{ render_field(field, id=False) }}
Explaination:
Because you have ****kwargs**, you can make the id=False and that would be more dymanic. You can choose when to remove ID.
Hope this help for those who have googled this solution
Related
I have this code which takes the name into the "nm" variable
{% extends "base.html" %}
{% block title %}Search Page{% endblock %}
{% block content %}
<form action="#" method="post">
<p>User or Group:</p>
<p><input type="text" name="nm"/></p>
<p><input type="submit" value="submit"/></p>
</form>
{% endblock %}
I want to put this variable into a different html file which will show different things.
Can anyone suggest me the most efficient way to make this happen?
If you're using Django, send the nm text field back to your view in views.py, where you should access that variable (nm = request.POST.get("nm")) and then send that via the context variable in the render() function to your other HTML file (return render(request, "your_other_file.html", {"nm": nm})), where you can access the variable via interpolation ({{ nm }})
why is it i cant put value from my database to input type date? even though my query is correct?
{% for feedback in feedbacks %}
<input name="datef" value="{{feedback.dateSubmitted}}" type="date">
{% endfor %}
this is my views.py
feedback = obj.objects.all()
print(feedback)
this is the result for print
<QuerySet [<TrEmployeeSuppliersFeedbackQuestionsSubmittedRecords: mystudent>]>
my models.py
class TrEmployeeSuppliersFeedbackQuestionsSubmittedRecords(models.Model):
.....
dateSubmitted = models.DateField(auto_now_add=True, null=True, blank=True)
.....
the result in my webview
UPDATE: i change my html to this , and this is the result in my webview
html
{% for feedback in feedbacks %}
{{feedback.dateSubmitted}} <input name="datef" value="{{feedback.dateSubmitted}}" type="date">
{% endfor %}
I suspect the formatting is off. The date input probably wants something like year-month-date. Try passing it like this:
<input name="datef" value="{{feedback.dateSubmitted|date:'Y-m-d'}}" type="date">
If the above doesn't work, also try:
<input name="datef" value="{{feedback.dateSubmitted|date:'d/m/Y'}}" type="date">
for all user inputs i think it will be better to use django forms or ModelForms
after that django will format all values for you and it will be more cleaner way to validate user data, and save it to database. for multiple forms you can use formset
in view you create formset:
TrEmployeeSuppliersFeedbackQuestionsSubmittedRecordsFormSet = modelformset_factory(
TrEmployeeSuppliersFeedbackQuestionsSubmittedRecords,
fields=('dateSubmitted ', )
)
formset = TrEmployeeSuppliersFeedbackQuestionsSubmittedRecordsFormSet()
and add formset as parameter to your html template
and then in html template you can
{{ formset.management_form }}
{% for form in formset %}
{{ form.dateSubmitted.value }} {{ form.dateSubmitted }}
{% endfor %}
I am trying to post all checked input checkboxes. The input field is generated by django's for loop as shown below.
From what I have found so far, the below should be working. I believe the issue may be in the fact that the input fields are generated through the forloop, if so, how can I get around this? For each value add to list and post with js?
index.html
{% for q in list %}
{% if forloop.last %}
<form method="POST" name="selectedchecks"> {% csrf_token %}
<div class="qblock">
<label class="pure-material-checkbox">
<input class="selectedchecks" type="checkbox" name="choices[]" value="{{ q }}">
<span>
<p>{{ q }}</p>
</span>
</label>
</div>
</form>
{% endif %}
{% endfor %}
views.py
if request.method == 'POST':
selected_list = request.POST.getlist('choices[]')
What happens is that only the first value of {{ q }} is returned if the first checkbox is selected, if any other checkbox apart from the first is selected, nothing is returned (empty list). Selecting all checkboxes also only returns the first value.
It should POST all selected checkbox values.
Any help is appreciated!
UPDATE
The problem was that the form was being re-initialized for every loop iteration. Setting the <form> tag before the loop fixed the issue!
I'm using Django to construct a simple personal website. I just built a basic email form. Here's the models.py file for it:
from django.db import models
class Message(models.Model):
name = models.CharField(max_length=200, unique=True)
email = models.EmailField(unique=True)
subject = models.CharField(max_length=100, unique=True)
message = models.CharField(max_length=1000, unique=True)
def __unicode__(self):
return self.name
And here is the corresponding forms.py file:
from django import forms
from rksite.models import Message
class EmailForm(forms.ModelForm):
name = forms.CharField(max_length=200,help_text="Name:")
email = forms.EmailField(help_text="Email:")
subject = forms.CharField(max_length=100, help_text="Subject:")
message = forms.CharField(max_length=1000, widget=forms.Textarea, help_text="Message:")
class Meta:
model = Message #link the model to the form
And finally, I'll also include the form's html page below:
{% extends 'rksite/base.html' %}
{% block title %}RaghavKumarContact{% endblock %}
{% block content %}
<h1>Contact Me</h1>
<br />
<form class="span6" id="email_form" method="POST" action="/home/contact/">
{% csrf_token %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field|linebreaks }}
{% endfor %}
<br />
<button class="btn btn-primary" type="submit" name="send">Send</button>
</form>
{% endblock %}
Now, no matter what I do, the "br/" tag shows up inside the "Message" Textarea field. Here's what I see on my webpage:
How can I get rid of this tag from this Textarea?
EDIT:
This is what it'll look like if I don't have the linebreaksfilter applied:
What is an alternative to the linebreaks filter??
Don't use linebreaks here:
{{ field|linebreaks }}
That renders the widget for the form, then passes the entire rendered HTML block through the linebreaks filter. That filter converts newlines into <br /> tags, and the rendering for a Textarea widget includes a newline before the text:
def render(self, name, value, attrs=None):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
return format_html('<textarea{}>\r\n{}</textarea>',
flatatt(final_attrs),
force_text(value))
(Source from https://github.com/django/django/blob/master/django/forms/widgets.py#L435)
I'm not sure why you'd want to pass the field values though linebreaks - an HTML textarea should handle regular linebreaks in the message text just fine, if that's what you're worrying about.
{% autoescape false %}
{% set label = '<i class="flaticon solid plus-1"></i>Add User'|raw %}
{{ form_row(form.submit, { 'label': label }) }}
{% endautoescape %}
This is the output
<i class="flaticon solid plus-1"></i>Add User
How do I get it to not escape? If I just print out label instead of supplying it as a parameter to the "form_row" function, it prints out properly.
You're using the |raw filter at the wrong place - it is only processed when outputting data, not when setting a variable. You should patch it into the form_row function, or append it to it's call - can't be sure without seeing how that function works.
Most probably this will fix it:
{{ form_row(form.submit, { 'label': label })|raw }}
Since I assume it returns the modified string and lets the {{ tags handle output.
in form_div_layout.html.twig
change
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain) }}</button>
to
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain)|raw }}</button>
This seems like a hacky solution, since I'm modifying the stuff in the vendor folder.