To get some more control over my input fields, I try to "copy" the function that generates input fields in the template
I use a ModelForm and I want to change
...
{{ form.name }}
...
into something like
...
<input id="{{ form.name.auto_id }}" type="text" name="{{ form.name.name }}" maxlength="{{ form.name.**get_max_length** }}" value="{{ form.name.**get_value_or_initial_value** }}"/>
...
Most of that works already, except maxlength and value.
maxlength
I read
How can I programmatically obtain the max_length of a Django model field?
Django: model maxlength and form maxlength
but I still don't get it right...
value
The answer to this question (How can you manually render a form field with its initial value set?) points to a ticket which is fixed already. Still name.value would print "None" if there is no value present. Am I meant to catch value="None" manually or is there a better solution meanwhile?
[edit]
value seems to work like that
{{ form.name.value|default_if_none:"" }}
(from Display value of a django form field in a template?)
You can get the max_length attribute from the widget. For the initial value, you only need to access the value attribute, there is already an initial or submitted value. All initial values passed to form class are held in form.initial, but you probably don't need to check these values:.
<input id="{{ form.name.auto_id }}" type="text" name="{{ form.name.name }}" maxlength="{{ form.name.field.widget.attrs.max_length }}" value="{% if form.name.value %}{{ form.name.value }}{% endif %}"/>
Related
I'm trying to dynamically set the value of a radio field within the HTML template but I'm not sure how to set the default selection. I want to do this because the forms I want to use are forms that can be saved and re-edited if need be, so I want the default values to be values set when previously saved/submitted.
the wtform fields
field_1 = StringField('field_1')
radio_1 = RadioField('radio_1', choices=[(1,'Yes'),(2,'No')])
what i want to be able to do is something like this:
data is database data
{% if data.field_1 = 'X' %}
{{ form.radio_1(id="radio_1",class="ff-style-radio",default=1) }}
{% else %}
{{ form.radio_1(id="radio_1",class="ff-style-radio",default=2) }}
{% endif %}
I haven't had any success trying this method, swapping default for value, etc. Is something like this possible? If not how would I separate the wtform radio field choices so I can just manually mark which selection is checked? Or should I just use the base HTML method and do something like this:
<ul class="ff-style-radio" id="radio_1">
<li>
{% if data.field_1 = 'X' %}
<input id="radio_1-0" name="radio_1" type="radio" value="Yes" checked>
{% else %}
<input id="radio_1-0" name="radio_1" type="radio" value="Yes">
{% endif %}
<label for="radio_1-0">Yes</label>
</li>
<li>
{% if data.field_1 = 'X' %}
<input id="radio_1-1" name="radio_1" type="radio" value="No">
{% else %}
<input id="radio_1-1" name="radio_1" type="radio" value="No" checked>
{% endif %}
<label for="radio_1-1">No</label>
</li>
</ul>
Thanks for any help
If you want to use the form to edit data already in your database, you should supply this data to the form at creation time in your view function. This will allow you to keep your templates simple and reusable. Data from the database can be passed to the form either as an object or as a dictionary https://wtforms.readthedocs.io/en/stable/forms.html. If your form maps directly to a database table you can just pass this unmodified from your query. In the following code I've followed your example and created a new dictionary to set the value of radio_1 based on the value of field_1.
#app.route("/myurl")
def myview():
# do database lookup here
olddata = {"radio_1": 1 if data.field_1 == "X" else 2}
form = Myform(formdata=request.form, data=olddata)
if request.method == "POST" and form.validate():
# .....
This code works, except that the populated date is format 2000-08-08. and the date picker is looking for 01-01-2000.
<form class="form form-inline" method="post" role="form">
{{ form.hidden_tag() }}
{{ wtf.form_errors(form) }}
<input data-provide="datepicker" format="mm/dd/yyyy" id="deadline" type="text" value="{{ form.deadline.data }}" name="deadline" required></input>
{{ wtf.form_field(form.complete) }}
{{ wtf.form_field(form.note) }}<br>
{{ wtf.form_field(form.submit) }}
</form>
how do i change either the prepopulated format, or the format datepicker wants?
in my model i have
deadline =DateField( 'Deadline (mm/dd/yyyy)', format='%m/%d/%Y',validators = [Required()])
can i change it in the view?
#app.route('/edit/<name>', methods=['GET', 'POST'])
def edit_task(name):
ptask=models.Tasks.query.filter_by(task=task).first()
form = task_form(obj=ptask)
form.populate_obj(ptask)
tform=task_form(request.values)
update
changing the formatting line as in
<input data-provide="datepicker" data-date-format="mm/dd/yyyy" id="deadline" type="text" value="{{ form.deadline.data }}" name="deadline" required></input>
had no effect, and the date still renders Year/mo/da
But, adding this to my view (as suggested below)
ptask=models.Tasks.query.filter_by(task=task).first()
form = task_form(obj=ptask)
form.populate_obj(ptask)
form.deadline.data = ptask.deadline.strftime("%m/%d/%Y")
fixed it.
Thanks
For Bootstrap Datepicker, the correct date format attribute is data-date-format as mentioned in the docs. Updated code for the datepicker –
<input data-provide="datepicker" data-date-format="mm/dd/yyyy" id="deadline" type="text" value="{{ form.deadline.data }}" name="deadline" required></input>
Above correction should solve your issue. But since you asked, you can also set the desired date format in the view –
form.deadline.data = ptask.deadline.strftime("%m/%d/%Y")
You can insert this line at the last (or second last) line of your view code after you have populated the rest of the fields in the form.
I'm trying to set maxlength html attribute in django template but when I try to get the value I specified in my model by using {{field.max_length}} nothing is displayed. I can get any other field value just fine.
Relevant Snippet:
{% for field in form %}
{% if "_color" in field.name %}
<div class="control-group">
<label class="control-label">{{field.label}}</label>
<input type="text" ng-init="{{field.name}}='{{field.value}}'" ng-model="{{field.name}}" ng-change="{{field.name}}_picker={{field.name}}" placeholder="{{field.label}}" maxlength="{{field.max_length}}">
The field you get by iterating trough your form is actually a forms.BoundField, and does not have all the attributes of your Field. You can access the Field instance through the field attribute of your BoundField. So, {{ field.field.max_length }} should work.
I'm looking at a package called crispy forms I was wondering if it was possible to change the html name from within the template?
i.e.
{{ form.username|changename }}
Rules:
I don't want to change the original form or view (at all), I only have access to the template.
Since you're changing the label, I suggest you do it template-ish, without using a templatetag or a filter:
<label for="id_username">Your label name here:</label>
{{ form.username }}
Or, if you can't resist, you have to apply a filter to your field.label property:
{{ form.username.label|my_custom_filter }}
A simple filter could be:
#register.filter(name='my_custom_filter')
def my_custom_filter(value):
# here value is the value of your label
# process it as you please then return the new value
if value == 'changeme':
return 'changed label'
return value
This is just an example to show you how a template filter works, you have then to elaborate it and change name, logic etc etc
This could be over simplifying it, but what not just raw output it?
<label for="">what ever you want</label>
<input type="text" name="{{ form.username.html_name }}" id="{{ form.username.auto_id }}">
I would still do this in the form.py myself but if all you have is the template to work with then it does not need anything fancy here.
i need a small help.. i am looping over objects which are in db and rendering all objects to template, so far so good. but what i want is that every rendered html name field should have different name so that i can refer to all of them latter. my code is this:
{% for p in products %}
<input type="number" name="name1" value="{{p.arg1}}" size="12"/>
<input type="number" name="name2" value="{{p-arg2}}" size="12"/>
{% endfor %}
but if i have 4 objects in DB, then i will have 8 rendered input fields in template, but all of them will have the "name" value as name1 and name2, is it possible to create 8 different names dynamically so that i can refer to all of them in my view again...
thanks
Use the forloop.counter variable
{% for p in products %}
<input type="number" name="name-{{forloop.counter}}-arg1" value="{{p.arg1}}" size="12"/>
<input type="number" name="name-{{forloop.counter}}-arg2" value="{{p.arg2}}" size="12"/>
{% endfor %}
The forloop.counter is 1-indexed. There is also the forloop.counter0 for indices
starting with 0.
Are you sure though that django formsets isn't what you need?