Why is this django formset not being submitted? - django

i have a formset as follows:
EduFormSet = formset_factory(forms.CandidateDegreeForm, can_delete=True)
edu_formset = EduFormSet(prefix='candidate_degree')
in the templates i am doing the following:
{% if edu_formset %}
{% for form in edu_formset %}
<div class="formset-form" style="visibility: visible;">
<form id="{{ form.prefix }}" method="POST" action="/degree/add/">
<h4>Some Heading Here</h4>
{% csrf_token %}
{% for field in form %}
{% include "form_field.html" %}
{% endfor %}
</form>
<script type="text/javascript">
jQuery(document).ready ( function(){
jQuery('{{ form.prefix }}').validationEngine();
});
</script>
<div class="clearfix"></div>
</div>
{% endfor %}
{{ edu_formset.management_form }}
<div class="button-container right">
<input class="button" type="submit" value="submit" />
</div>
{% endif %}
I am not sure why but nothing really happens when i hit the submit button.

Your submit button is not within the form, so the action is not triggered by the click!
Here's how the docs show you to render formsets:
<form method="post" action="">
<!-- Notice how the formset (below) and thus its submit button
is INSIDE the form (above) -->
{{ formset.management_form }}
<table>
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
</form>
You try to create multiple forms with the form.prefix for id. This could work but each form would have to be rendered with its own submit button. Formsets are designed to combine multiple forms into one and guarantee uniqueness of value names by said prefix. They would be enclosed in a singe form and share any submit triggers.

Related

How to add classes to subforms within formset in django-crispy-forms

What I'm after is the ability to style forms within my formset:
<form>
{{ formset management stuff here }}
<div class="formset-child">
{{ formset child form here }}
</div>
<div class="formset-child">
{{ formset child form here }}
</div>
</form>
Is there a way to do this cleanly with the FormHelper (as for adding submit buttons etc.) or do I need to do it in my template and manually loop over the formset?
You can use layout.HTML() block to render the inline forms there like this:
layout_blocks = []
layout_blocks.append(layout.Fieldset(
_("Children"),
layout.HTML("""{% load crispy_forms_tags i18n %}
{{ formsets.children.management_form }}
<div id="children">
{% for form in formsets.children.forms %}
<div class="child formset-form">
{% crispy form %}
</div>
{% endfor %}
</div>
<!-- used by javascript -->
<div id="children_empty_form" class="child formset-form" style="display: none">
{% with formsets.children.empty_form as form %}
{% crispy form %}
{% endwith %}
</div>
"""),
css_id="children_fieldset",
))
layout_blocks.append(bootstrap.FormActions(
PrimarySubmit('submit', _('Save')),
))
self.helper.layout = layout.Layout(*layout_blocks)
Each of your inline forms can have the helper with its own layout.

Dynamic Formset with crispy forms and django-dynamic-formset not working

I'm trying to use the app django-dynamic-formset to allow users to add more than one media object at the end of a form.
I'm following the demo here.
https://github.com/elo80ka/django-dynamic-formset/blob/master/docs/usage.rst
I managed to get this to work but then changed to using crispy form and it's no longer working.
The "add another" text isn't appearing aver the first inline formset.
The template looks like this.
<form id="dtuForm" enctype="multipart/form-data" action="." method="post" >
{% csrf_token %}
{{ formset.management_form }}
{% crispy form %}
<fieldset class="" id="formaddtest" >
{% for formset in inlines %}
<div id = "media_object">
{% for subform in formset.forms %}
{{ formset.management_form }}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Add Link / Downloadable File</h3>
</div>
<div class="panel-body">
{% crispy subform %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</fieldset>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "star" %} Submit
</button>
{% endbuttons %}
</form>
I'm starting to suspect that I'm not putting the media_object selector in the right place but I'm not sure where to put it now that I'm using crispy forms so any help or pointers is useful to me.
Thanks

django form wizard, does not go to second step

I am trying to perform the following using Django :
Wizard containing two formds
First form is a simple form containing some Ajax to compute automatically some fields
Second form is a user registration
The problem is the following :
The first form is displayed correctly and the Ajax within the page is working fine
The second form is never displayed after pushing on the button "submit"
The code is as follows :
urls.py
from forms import InsertPropertyForm1, InsertPropertyForm2
from views import InsertPropertyWizard
urlpatterns = patterns('',
url(r'^addProperty/$', InsertPropertyWizard.as_view([InsertPropertyForm1, InsertPropertyForm2]), name='addProperty'),
)
views.py
FORMS = [("property", InsertPropertyForm1),
("test", InsertPropertyForm2)
]
TEMPLATES = {'0': 'realEstate/addProperty.html',
'1' : 'realEstate/test.html',
}
class InsertPropertyWizard(SessionWizardView):
def get_template_names(self):
print ("next step !!!!! " + str(self.steps.current))
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
print "Wizard done"
#do_something_with_the_form_data(form_list)
return HttpResponseRedirect('http://TO_FILL_IN')
realEstate/addProperty.html
{% extends 'realEstate/base.html' %}
{% load socialaccount %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<h1> Insert an ad </h1>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form class="form-horizontal" role="form" action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
</table>
{{ form.non_field_errors }}
<fieldset>
<legend>Localisation</legend>
<div class="form-group">
{{ form.country.errors }}
<label class="col-lg-1" for="id_country">{{form.country.label}}</label>
<div class="col-lg-1">
{{ form.country }}
</div>
</div>
</fieldset>
</fieldset>
{% 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 %}
Just thought it could help someone.
Problem was that one of the field was not defined in the form and I forgot to include it in the template.
The behaviour of the wizard was correct. It got stuc on the first page but did not display the error on the screen as the field was not displayed.
Got me crazy but it was my fault.
Cheers

Trying to access ModelForm field modelChoice choices in Django template

I'm generating ModelForms and want some granular control over how they are output in my template. Specifically, I need to add some markup to the end of each radio button in each of my select lists.
Code:
# order-form.html
{% load catname %}
<form id = "order-form">
{% for form in forms %}
<div id="gun-{{ forloop.counter }}">
{% for field in form.fields %}
<div id="{{ field }}-item" class="item">
<h3>{{ field|catname }}</h3>
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
</div>
{% endfor %}
{% endfor %}
<button type="submit" id="standard-gun-form-submit">Continue to next step</button>
</form>
# views.py
def get_form(request):
if request.method == 'POST':
if request.POST['gun_type'] == 'standard':
forms = [StandardGunForm(prefix=p) for p in range(0,2)]
return render_to_response('main/order-form.html', {'forms' : forms,}, RequestContext(request))
# forms.py
class StandardGunForm(ModelForm):
def __init__(self, *args, **kwargs):
super(StandardGunForm, self).__init__(*args, **kwargs)
for field in self.fields:
if isinstance(self.fields[field], ModelChoiceField):
self.fields[field].empty_label = None
class Meta:
model = BaseGun
widgets = {
'FrameTuning' : RadioSelect(),
'FrameConnection' : RadioSelect(),
}
exclude = ('price')
Endgame: markup that looks like this
<form id="foo">
<div class="category">
<div class="item">
<input type="radio" name="srsbzns" value="1">Option 1</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="2">Option 2</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="3">Option 3</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
</div>
</form>
From the shell, this returns what I want
>>> forms = [StandardGunForm(prefix=p) for p in range(0,2)]\
>>> forms[0].fields['frame_tuning'].choices.queryset
I'm surprised this is proving so challenging!
Bonus: I have DEBUG = True and Django Debug toolbar enabled. Is it possible to dump the variables to the browser, so I can see what this stuff looks like as I drill down?
Thanks!
I had to do something similar and started down this path as well. I wanted to create table rows from a ModelChoiceField where each column had a different field of the model instance (and then I'd allow filtering the table rows via JavaScript).
I couldn't find it in the Django docs, but a quick perusal of the Django source showed the way. You can get to the queryset to access the model instances like so:
<form action="{% url 'some_view' %}" method="post">
{% csrf_token %}
{% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}
{% for field in form %}
{{ field.label }}
{% if field.field.choices %}
{% for model_instance in field.field.choices.queryset %}
{{ model_instance.id }}
{% endfor %}
{% else %}
{{ field }}
{% endif %}
{% if field.errors %}
{{ field.errors|striptags }}
{% endif %}
{% endfor %}
<button type="submit">Submit</button>
</form>
However, at this point we've disassembled the shiny widget (in my case a CheckboxSelectMultiple) and must re-assemble the HTML form input using template code. I found no direct way to simultaneously iterate over the ModelChoiceField to access the model instance fields and get the HTML form tags for the choices.
Maybe there's a way, but I abandoned my attempt and built my own HTML form, handling all the POST data in a view. It ended up much easier that way. ModelForms are really nice and convenient, but using them for something they weren't built for can end up being more difficult.
I figured I'd post this in case anyone is trying to do it for some other reason. Hope it helps.
Very late, but I'm reading now and this is what it worked for me
{% for field in form %}
{% for x, y in field.field.choices %}
{{x}}
{{y}}
{% endfor %}
{% endfor %}
Where "x" is the id or code, and "y" is the readable value or title.
You can access the underlying model instance for each choice:
{% for choice, label in form.field_name.field.choices %}
{{ choice.value }}
{{ choice.instance }}
{{ choice.instance.instance_attribute }}
{{ label }}
{% endfor %}
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
Look what you're doing here, you're literally trying to access a field called "field" every time in this loop, which presumably does not exist.
You need to take the field object you're iterating through, and access the choices attribute on that.
{% for field in form.fields %}
{% for choice in field.choices %}

django change form field in .html template output

I create a form based on a model , like seen below:
class ContactSelectionForm(forms.ModelForm):
contacts = ManyToManyByLetter(Contact, field_name="first_name")
class Meta:
model = ContactSelection
exclude = ('created_by',)
When I process this view I see at the .html output a field labeled with "Contact".
Now I`m wondering whether it is possible to change this output. For example I want to name this field not "Contact" but "Selected Contacts".
This is the form processing part of the .html template:
<form action="{{ request.path }}" method="POST">
<div>
<fieldset class="module aligned">
{% for field in form.visible_fields %}
<div class="form-row">
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</fieldset>
</div>
</form>
If somebody is wondering what ManyToManyByLetter(Contact, field_name="first_name") in the form is, check out http://code.google.com/p/django-ajax-filtered-fields/ . A very helpful many2many javascript library.
Did you try setting the fields label?
(the docs)
contacts = ManyToManyByLetter(Contact, field_name="first_name", label="Selected Contacts")