HiddenField not returning a value - flask-wtforms

I cannot find out why this code works with StringField, but not with HiddenField. The variable date2 was added just for debugging the issue.
(Actually, I can leave StringField there, but it took me some time to find the problem and I would like to understand what is wrong in order not to repeat the mistake)
Form definitions:
DAYS = 10
class _OneDayForm(Form):
alarmtime = StringField(validators=[Optional(), validate_time])
date2 = StringField() # json encoded [Y,M,D]
date = HiddenField() # json encoded [Y,M,D]
class _PerDayForm(Form):
days = FieldList(FormField(_OneDayForm), min_entries=DAYS)
submit = SubmitField()
Jinja2 template:
<input name="{{ subform.date.name }}" type="hidden" value="{{ ymd }}">
<input name="{{ subform.date2.name }}" type="hidden" value="{{ ymd }}">
Generated HTML:
<input name="days-0-date" type="hidden" value="[2016, 12, 7]">
<input name="days-0-date2" type="hidden" value="[2016, 12, 7]">
StringField date2 returns its value, but HiddenField date does not. I tried to swap them to be sure that StringField vs. HiddenField really is the only difference.

Just for the record, I have found the bug:
I was using {{ subform.hidden_tag() }} to display the CSRF token, but it does more than this (and I was not knowing it):
If your form has multiple hidden fields, you can render them in one
block using hidden_tag().
So my hidden field was rendered twice and the first one had no value.

Related

How to style mixed django form better

I have theese two forms:
class InitialForm(Form):
trn = IntegerField(widget=NumberInput, required = False)
klient = ChoiceField(choices=KLIENTS, required = False)
class SecondForm(Form):
faktura = CharField(max_length = 200, required=False)
In the form I'm mixing django forms and pure html select (because I needed to pull out some data from a database)
<form method="POST" novalidate>
{% csrf_token %}
<label for="{{ form.klient.id_for_label }}">Klient: </label>
{{ form.klient }}
<br><br>
<label for="programs">Program: </label>
<select id="programselect" name="programs">
{% for option in options %}
<option value="{{ option.0}}">{{ option.1 }}</option>
{% endfor %}
</select>
<br><br>
<label for="{{ form.trn.id_for_label }}">Trn: </label>
{{ form.trn }}
<br><br>
<label for="{{ form2.faktura.id_for_label }}">Faktura: </label>
{{ form2.faktura }}
<br>
<button type="submit" class="btn btn-secondary">Search</button>
</form>
So far, I tried it with &nbsp& to have the inputs above each other.
How would you style it better with CSS?
Assuming you're using the crispy template pack for styling, you could create a model form class and give the programs field initial "options" from the database, using a query from whatever model you're storing the "options" on. Here's an example, using some assumptions about your database schema:
class ProgramForm(forms.ModelForm):
class Meta:
fields = ['program']
model = MyRecord
def __init__(self, *args, **kwargs):
super(ProgramForm, self).__init__(*args, **kwargs)
self.fields['program'].queryset = Option.objects.filter(some_field=True).order_by("option_name")
Using this kind of solution, you're using your backend model form class to handle passing the "option" data, and doing all your styling in the html with crispy. Note that if you're using two separate forms, pass them to your template with different names, like:
{{form.klient|as_crispy_field}}
{{program_form.program|as_crispy_field}}
Additionally, you can use Django's widgets to add functionality to your options selector, for example if you wanted checkboxes instead of a dropdown select (ForeignKey vs M2M, let's say).
If you can do none of that and must use this HTML structure and backend approach, you can still target the form with CSS, for example something like:
<style>
#this-label span {
margin-right: 100px;
}
</style>
<label for="{{ form.trn.id_for_label }}" id="this-label"> <span>Trn:</span> </label>
...will add space to the right of "Trn:". This is just one way of doing that, but you could add a class to the span element and target multiple such tags.

How to display date in an input with twig and symfony?

I can't store the actual day in my date input type.
When I set up the twig line to get the date, it works perfectly but then when I try to store it in my input it doesn't display it.
twig
{#This line provides the day of today#}
{{ "now"|date("d/m/Y") }}
twig
{#Then this line doesn't changes the value of the input#}
<input type="date" value="{{ "now"|date("d/m/Y") }}" class="form-control" name="date">
this is neither a twig nor a symfony problem...
the format for <input type="date">'s value is YYYY-mm-dd. The display is something different. <input type="date"> will format depending on user locale and stuff.
see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date

How to render a checkbox group with fields from an Entity with Symfony2

I have a material table that is related to items_budget. The form for items_budget needs to list all the registered material as a checkbox group, and beside each checkbox, two input fields, for quantity and price. Below is the code block I wrote for rendering this piece:
<strong>Materiais</strong>
{% for material in materials %}
<div class="checkbox">
<label>
<input type="checkbox" class="itemsbudget_material" name="cdg_itemsbudget_type[material]" value="{{ material.id }}"> {{ material.name }} -
</label>
<input type="hidden" class="itemsbudget_price_hidden" value="{{ material.price }}"/>
<input type="text" class="itemsbudget_quantity" name="cdg_itemsbudget_type[quantity]" placeholder="Qtd" size="3"/>x - R$
<input type="text" class="itemsbudget_price" name="cdg_itemsbudget_type[price]" value="0" size="3" readonly/>
</div>
{% endfor %}
The problem I am facing can be seen in the image. Looking at the top-left image, you see I have marked "Material C", filled the quantity, and after submitting the form, as shown in the second image, everything is fine.
But if I do the same with another Material, as it can be seen in the last image of my table, the quantity field is NULL.
What happens here is that only the first register in the material form is, let's say, "seen". When I say "first register" I mean the lowest id in the material form, literally the FIRST. If I had deleted the "Material C", then "Material D" would be the first and the quantity field would be seen for it only.
I have tried to put at the end of each name attribute a pair of brackets, but by doing it the page is refreshed and nothing is persisted, nothing happens.
I have tried many different ways to render this. Also, I have tried to create my material field as a collection, but I really think this is not the solution because I must get the id, quantity and price entered in the fields. I would need to be able to render something exactly like this with a collection form.
Please I need guidance. If you need any more code I will be happy to update my question. Thank you.
The value of quantity field is null, because the name of field is cdg_itemsbudget_type[quantity], the value override by last quantity field which is empty, the name of your field must be array with unique index something like this:
<input type="text" class="itemsbudget_quantity" name="cdg_itemsbudget_type[quantity][{{ material.id }}]" placeholder="Qtd" size="3"/>x - R$
And then you have array of quantity for each material.

RactiveJS dynamic variable name

I'm curious if I can somehow use dynamic variable names in templates. For example, I'm having a loop, though a type of units in my game:
{{# config.units:unit }}
<input type="text" id="unit_{{unit}}" class="toTrain selectable" value="" placeholder="0" />
{{/ config }}
Where the value of the input should return the value of {{units_1}} for example, which represents the amount of units (type 1).
I could easily do some external object and store the amount of units for each of them but, I was wondering if I can keep the data binded because somewhere in the template there will be a total needed resources which is calculated whith these values.
The only "solution" which came into my head was to get rid of the loop and manually write the units in the template. But, when units change, I also need to change the template, and.. the real template structure for one unit is a bit bigger than this snippet.
Example:
<input value="{{units_1}}" />
<input value="{{units_2}}" />
And I was looking for something like:
<input value="{{'units_'+unit}}" />
Which is obviously not working and not even supposed to work this way. But, thats why I'm here right ? To raise questions.
Regards !
Try to use write getUnit function:
{{# config.units:unit }}
<input type="text" id="{{ getUnit(unit) }}" class="toTrain selectable" value="" placeholder="0" />
{{/ config }}
Component:
Ractive.extend({
init:function(){
self.set("getUnit", function (id) {
return self.get("config.units.unit_"+id);
});
}
})

Add a css class to a field in wtform

I'm generating a dynamic form using wtforms (and flask). I'd like to add some custom css classes to the fields I'm generating, but so far I've been unable to do so. Using the answer I found here, I've attempted to use a custom widget to add this functionality. It is implemented in almost the exact same way as the answer on that question:
class ClassedWidgetMixin(object):
"""Adds the field's name as a class.
(when subclassed with any WTForms Field type).
"""
def __init__(self, *args, **kwargs):
print 'got to classed widget'
super(ClassedWidgetMixin, self).__init__(*args, **kwargs)
def __call__(self, field, **kwargs):
print 'got to call'
c = kwargs.pop('class', '') or kwargs.pop('class_', '')
# kwargs['class'] = u'%s %s' % (field.name, c)
kwargs['class'] = u'%s %s' % ('testclass', c)
return super(ClassedWidgetMixin, self).__call__(field, **kwargs)
class ClassedTextField(TextField, ClassedWidgetMixin):
print 'got to classed text field'
In the View, I do this to create the field (ClassedTextField is imported from forms, and f is an instance of the base form):
f.test_field = forms.ClassedTextField('Test Name')
The rest of the form is created correctly, but this jinja:
{{f.test_field}}
produces this output (no class):
<input id="test_field" name="test_field" type="text" value="">
Any tips would be great, thanks.
You actually don't need to go to the widget level to attach an HTML class attribute to the rendering of the field. You can simply specify it using the class_ parameter in the jinja template.
e.g.
{{ form.email(class_="form-control") }}
will result in the following HTML::
<input class="form-control" id="email" name="email" type="text" value="">
to do this dynamically, say, using the name of the form as the value of the HTML class attribute, you can do the following:
Jinja:
{{ form.email(class_="form-style-"+form.email.name) }}
Output:
<input class="form-style-email" id="email" name="email" type="text" value="">
For more information about injecting HTML attributes, check out the official documentation.
If you would like to programatically include the css class (or indeed, any other attributes) to the form field, then you can use the render_kw argument.
eg:
r_field = RadioField(
'Label',
choices=[(1,'Enabled'),(0,'Disabled')],
render_kw={'class':'myclass','style':'font-size:150%'}
)
will render as:
<ul class="myclass" id="r_field" style="font-size:150%">
<li><input id="r_field-0" name="r_field" type="radio" value="1"> <label for="r_field-0">Enabled</label></li>
<li><input id="r_field-1" name="r_field" type="radio" value="0"> <label for="r_field-1">Disabled</label></li>
</ul>
In WTForms 2.1 I using extra_classes, like the line bellow:
1. The first way
{{ f.render_form_field(form.email, extra_classes='ourClasses') }}
We can also use #John Go-Soco answers to use render_kw attribute on our form field, like this way.
2. The second way
style={'class': 'ourClasses', 'style': 'width:50%;'}
email = EmailField('Email',
validators=[InputRequired(), Length(1, 64), Email()],
render_kw=style)
But I would like more prefer to use the first way.
Pretty late though, but here is what I found. While rendering a template you can pass any key-value pairs inside the parenthesis, and it just puts those key values while rendering.
For example, if you had to put a class along with some placeholder text you can do it like below:
{{ form.email(class='custom-class' placeholder='email here') }}
will actually render like below:
<input class="custom-class" id="email" name="email" placeholder="email here" type="text" value="">
Basically, you can even try experimenting by adding some non-existent HTML attribute with some value and it gets rendered.
To make it a less of pain its good to have helper functions as macros and render them instead of actual fields directly.
Let's say you have common classes and error-classes.
You can have a helper macro like this:
{% macro render_field(field,cls,errcls) %}
{% if field.errors %}
<div class="form-group">
<label for="{{ field.id}}">{{ field.label.text }}</label>
{{ field(class = cls + " " + errcls,**kwargs) | safe}}
<div class="invalid-feedback">
{% for error in field.errors %}
<span> {{error}}</span>
{% endfor %}
</div>
</div>
{% else %}
<div class="form-group">
<label for="{{ field.id}}">{{ field.label.text }}</label>
{{ field(class = cls,**kwargs) | safe}}
</div>
{% endif %}
{% endmacro %}
Now while rendering a field you can call like this with additional attributes like this in the template:
{{render_field(form.email,cls="formcontrol",errcls="isinvalid",placeholder="Your Email") }}
Here I have used bootstrap classes, just modify the helper function to your needs!
Hope that helps! Happy coding!

Resources