Django formset - not setting initial data when data is passed - python

I am creating form using Django Form wizard and formsets.
def get_form(self, step=None, data=None, files=None):
initial_data_set = []
for x in some_list:
initial_data_set.append({
'title' : x.title,
})
data = {
'form-TOTAL_FORMS': '5',
'form-INITIAL_FORMS': '5',
'form-MAX_NUM_FORMS': '',
}
formset_class = formset_factory(TitleForm, extra =0)
formset = formset_class(data=data, initial=initial_data_set)
return formset
Template
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block content %}
{% if wizard.form.forms %}
{% for form in wizard.form.forms %}
{{ form.media }}
{% endfor %}
{% else %}
{{ wizard.form.media }}
{% endif %}
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="." method="post" enctype="multipart/form-data">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% if ingestable_upload %}
<tr>{{ form.as_inline_table }}</tr>
{% else %}
{{ form.as_table }}
{% endif %}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
<input type="submit" value="{% trans "Submit" %}"/>
</form>
{% endblock %}
I was able to see initial data in my form when I was not passing 'data'. However, not passing data was giving me formset.is_valid as False and there was None in the cleaned_data. So I created data{} and passed it as per the documentation here -
https://docs.djangoproject.com/en/1.7/topics/forms/formsets/#understanding-the-managementform
Since I started passing data, form is not getting populated with initial data.
I have put debug statements in formsets.py under BaseFormSet() class. It is getting both data and initial data that I am passing.
I have been struggling with this for few days. Any help on how I can populate my form and get cleaned data will be great.

What you're doing is overriding your form initial data with your data object, data attribute is not necessary that data is passed on the {{ formset.management_form }} in your template.
There's something else wrong with your form. I would suggest you print the errors when is_valid fails and see what's missing.

Related

Python, Django: Editing inlineformset_factory

inside my app I'm using an inlineformset_factory and right know it's working fine! But when displaying it inside my template the labels are always staying right above the input-field. Is there any way to display them side-by-side or even move the label as some sort of placeholder inside the input-field?
views.py
formset = inlineformset_factory(Model_A, Model_B, can_delete=False, extra=0, fields=('fields_01', 'fields_02', 'fields_03'))
template.html
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<button type="submit">Save</button>
</form>
Thanks for all your help and have a great weekend!
Try this:
<form action="" method="POST">
{% csrf_token %}
{{ form.management_form }}
{% for field in form %}
{{field.product.label}} - {{field.product}} #here product is my field name
<hr>
{% endfor %}
<input type="submit" name="Submit">
</form>
You have to do this for every field
#Changes
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.Field_name.label }} - {{form.Field_name}} #1st field
{{ form.Field_name.label }} - {{form.Field_name}} #2nd field
{% endfor %}
<button type="submit">Save</button>
</form>
I think the displaying was influenced by css。
Use F12 to check css in chrome to find the reason。
You can edit the css to change the displaying.
Or use django-widgets-improved and bootstrap to set class to the fields of form.
{% load widget_tweaks %}
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{% render_field field class="form-control" %}
{% endfor %}
{% endfor %}
<button type="submit">Save</button>
</form>

Python Django template rendering from views gives me a too many values to unpack error

I have a function in views.py that renders the template in template.html shown below:
views.py
def example(request):
context_dict = {
'form_1': Step1Form,
'form_2': Step2Form,
'form_3': Step3Form,
}
return render(request, 'example/template.html', context_dict)
template.html
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in form_1 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in form_2 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in form_3 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>
But for some reason when I load the template, I get the error:
ValueError at /example/
too many values to unpack (expected 2)
The template will load if the field tag in the third form is gone. The context dictionary and rendering doesn't look any different from other ones that I've seen so I don't know what's causing the problem.
in your views.py, you seem to be passing the form class rather than an instance of the form. Maybe the answer is to call the class and make an instance for the template to render, by adding (). As long as these are unbound forms you can probably get away with:
context = { 'form_1': Step1Form(),
'form_2': Step2Form(),
'form_3': Step3Form()}
The value error maybe caused because the template cannot render the forms directly as they are passed as context_dict. So here is my solution:
views.py
def example(request):
context_dict = {
'form_1': Step1Form,
'form_2': Step2Form,
'form_3': Step3Form,
}
return render(request, 'example/template.html', {'context_dict':context_dict})
template
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in context_dict.form_1 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in context_dict.form_2 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>
<form method="GET" action="/example/">
{% csrf_token %}
<div>
{% for field in context_dict.form_3 %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label><br>
{{ field }}<br>
{% endfor %}
</div>
</form>

flask-admin: revise the button text

I haven't found similar questions on stackoverflow, I'd like to change the save button to submit or confirm on the edit form. I know this might not be easily changed. Thanks for any advise in advance.
After search in the code of flask-admin, I found the button is rendered with macro render_form, render_form_buttons, extra. The value of these buttons is hard code with {{ _gettext("blabla") }}.
As these buttons are not fields of data model, we can't use rendering rules to custom the value. I think there are two work arounds to get this done:
change the macro which render these buttons in the source of flask-admin(render_form_buttons, extra)
flask-admin use flask-babelex to do localization({{ _gettext("blabla") }}), you can 'translate' Save to submit or confirm with flask-babelex
UPDATE:
You can custom edit.html in your own template directory.
{% extends 'admin/model/edit.html' %}
{% from 'admin/lib.html' import extra with context %}
{% from 'admin/lib.html' import form_tag with context %}
{% from 'admin/lib.html' import render_form_fields with context %}
{% macro my_render_form_buttons(cancel_url, extra=None, is_modal=False) %}
<hr>
<div class="form-group">
<div class="col-md-offset-2 col-md-10 submit-row">
<input type="submit" class="btn btn-primary" value="{{ _gettext('Submit') }}" />
{% if extra %}
{{ extra }}
{% endif %}
{% if cancel_url %}
<a href="{{ cancel_url }}" class="btn btn-danger" role="button" {% if is_modal %}data-dismiss="modal"{% endif %}>{{ _gettext('Cancel') }}</a>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro my_render_from(form, cancel_url, extra=None, form_opts=None, action=None, is_modal=False) -%}
{% call form_tag(action=action) %}
{{ render_form_fields(form, form_opts=form_opts) }}
{{ my_render_form_buttons(cancel_url, extra, is_modal) }}
{% endcall %}
{% endmacro %}
{% block edit_form %}
{{ my_render_form(form, return_url, extra(), form_opts) }}
{% endblock %}

Iterating through a nested FormField

I'm trying to iterate through a FormField in a Formfield, which are both part of a FieldList.
In my views.py I'm calling for the mainForm, the template iterates successfully through the FormField subForm. However, when I can't get the iteration through the subSubForm to work. Those fields never appear in the browser.
Formcode:
class subSubForm(Form):
step = IntegerField("step", validators=[NumberRange(min=0, max=99)])
description = TextField("Description")
information = TextAreaField("Information Exchanged")])
class subForm(Form):
name = TextField("Description")
step = FieldList(FormField(subSubForm), min_entries=1)
class mainForm(Form):
sub_form = FieldList(FormField(subForm), min_entries=1)
And the Jinja2 template:
{% for sub_form in form.sub_form %}
{{ sub_form.form.name(placeholder='Scenario Title') }}
{% for error in name %}
{{error}}
{% endfor %}
{% for step in form.sub_form %}
{{ step.form.id(placeholder='#') }}
{{ step.form.description(placeholder='description') }}
{{ step.form.information(placeholder='info xch') }}
{% endfor %}
{% endfor %}
{% endfor %}
The above only shows the sub_form.form.name-field.
How can I do nested iteration so that the step fields are also shown?
It looks like you made mistake in second nested loop in your template. Here is its fixed version:
{% for sub_form in form.sub_form %}
{{ sub_form.form.name(placeholder='Scenario Title') }}
{% for error in name %}
{{error}}
{% endfor %}
{% for step in sub_form.step %}
{{ step.form.step(placeholder='#') }}
{{ step.form.description(placeholder='description') }}
{{ step.form.information(placeholder='info xch') }}
{% endfor %}
{% endfor %}
This renders to:
<input id="sub_form-0-name" name="sub_form-0-name" placeholder="Scenario Title" type="text" value="">
<input id="sub_form-0-step-0-step" name="sub_form-0-step-0-step" placeholder="#" type="text" value="">
<input id="sub_form-0-step-0-description" name="sub_form-0-step-0-description" placeholder="description" type="text" value="">
<textarea id="sub_form-0-step-0-information" name="sub_form-0-step-0-information" placeholder="info xch"></textarea>

How to get a certain field out of form in django template?

i wonder how i can add some extra html to a certain field in a template in Django
I have the following form (forms.py)
first_name = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
last_name = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
street = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
In my template i get the fields with:
<form action="" method="post">{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" value="Submit" />
</form>
Now i want to add some extra html to the street field like this
<form action="" method="post">{% csrf_token %}
{% for field in form %}
{% if field.type =='street' %}
<div class="fieldWrapper otherclass">
<hr>
{% else %}
<div class="fieldWrapper">
{% endif %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" value="Submit" />
</form>
The whole thing fails:
Could not parse the remainder: '=='street'' from '=='street''
Template operators require a space before and after so replace
{% if field.type =='street' %}
with
{% if field.type == 'street' %}
or use the ifequal templatetag
{% ifequal field.type 'street' %}
Hello world.
{% else %}
Apocalypse
{% endifequal %}

Categories