How to add multiple lines of the Formset? - django

i work on the form for users.
They have to add many model objects in the appropriate form.
one line is displayed when entering the GET method,
they will type in input name = "add-rows-number" the number should be displayed the number of forms in the formset
I tried with formset and with model formsetfactory
class AddCostCenters(View):
def __init__(self, *args, **kwargs):
super(AddCostCenters, self).__init__(*args, **kwargs)
self.FormSet = modelformset_factory(CostCenter, form=CostCenterAddForm, extra=self.get_form_size)
def get_form_size(self, request):
extra_rows_num = 1
if 'add-rows' in request.POST:
extra_rows_num += int(request.POST.get('add-rows-number'))
return extra_rows_num
def get(self, request, proceeding_id):
costcenter_model = CostCenter.objects.filter(
participation__provider__user=request.user,
participation__proceeding=proceeding_id
)
return TemplateResponse(request, 'costcenteradd.html', context)
def post(self, request, proceeding_id):
costcenter_model = CostCenter.objects.filter(
participation__provider__user=request.user,
participation__proceeding=proceeding_id
)
# if 'add-rows' in request.POST:
# try:
# rows_to_show = int(request.POST.get('add-rows-number'))
# except ValueError:
# rows_to_show = 0
# self.extra_rows_number += rows_to_show
if 'save_form' in request.POST:
new_cost_centers = []
post_formset_data = self.FormSet(request.POST)
if post_formset_data.is_valid():
instances = post_formset_data.save(commit=False)
new_cost_centers.append(instance)
# do something
else:
post_form = post_formset_data
context = {
'form': post_form,
}
return render(request, 'costcenteradd.html', context)
form
class CostCenterAddForm(forms.ModelForm):
# helper = CostCenterAddFormSetHelper()
def __init__(self, *args, **kwargs):
super(CostCenterAddForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_show_labels = False
for field_name, field in self.fields.items():
field.help_text = None
class Meta:
model = CostCenter
fields = (
'id',
'cost_center_account_no',
'cost_center_account_name',
'departmental_code',
'values_for_year',
'only_total_cost_of_cost_center',
)
exclude = (
'participation',
'to_check',
'is_checked',
'accepted',
'use_in_calculations',
)
html
<div class="container-fluid ">
<form method="post">
{% csrf_token %}
{{ form.management_form }}
<div class="row sticky-top text-center form-nav">
<div class="col-md-2 content_center"> Numer Konta OPK </div>
<div class="col-md-4 content_center"> Nazwa konta OPK </div>
<div class="col-md-2 content_center"> Kod resortowy </div>
<div class="col-md-1 content_center"> Rok za który jest postępowanie </div>
<div class="col-md-1 content_center"> Uproszczone dane finansowe </div>
<div class="col-md-2 content_center"> Usuń </div>
</div>
<div class="section sticky-top my-2 form-panel ">
<div class="row sticky-top my-2">
<div class="col-md-2">
<button class="btn btn-success btn-block" type="submit" name="save_form">Zapisz</button>
</div>
<div class="col-md-4">
<div class="input-group mb-3">
<input class="form-control" min="1" type="number" name="add-rows-number"
value={{form.total_form_count }}
placeholder="number" aria-label="add form rows ">
<div class="input-group-append">
<button class="btn btn-info" type="submit" name="add-rows">show_rows</button>
</div>
</div>
</div>
</div>
</div>
<hr>
{% for field in form %}
<div class="row text-center">
<div class="col-md-2 paste-in">
{{field.cost_center_account_no | as_crispy_field}}
</div>
<div class="col-md-4 paste-in">
{{field.cost_center_account_name | as_crispy_field}}
</div>
<div class="col-md-2 paste-in">
{{field.departmental_code | as_crispy_field}}
</div>
<div class="col-md-1 paste-in">
{{field.values_for_year | as_crispy_field}}
</div>
<div class="col-md-1">
{{field.only_total_cost_of_cost_center | as_crispy_field}}
</div>
<div class="col-md-2">
<input type="submit" name="del_btn{{ field.instance.id }}" value="del"
{% if field.instance.id == None %}
class="btn btn-outline-secondary" disabled
{% else %}
class="btn btn-outline-danger"
{% endif%} />
</div>
</div>

You need to create the formset in both your get() and post() methods and add it to your context. You use the queryset attribute to populate it with existing instances:
formset = self.FormSet(queryset=CostCenter.objects.filter(...))
# or
formset = self.FormSet(queryset=CostCenter.objects.filter(...), data=request.POST)
Then in your template, you loop through your formset (what you call form in your template is actually a formset):
{{ formset.management_form }}
{% for form in formset %}
{{ form.cost_center_account_no|as_crispy_field }}
...
{% endfor %}
In your definition of self.FormSet, set extra=1 so users have at least one extra row. Remove the calculation, because that cannot work. request isn't available in the __init__() of a View (it gets added with as_view()).
Now I would not have users submit the number of extra rows, you can just deduct it from the input data. Write some javascript to let users add rows themselves directly, like you see in the admin:
Add a + button to add an extra row
The javascript clones the previous row, adds it to the list of forms (with empty input fields)
The javascript also updates the value for TOTAL_FORMS and MAX_FORMS input fields (hidden fields in the management form)
This way when users submit the formset, it will have the extra rows.

Related

passing instance to Django modal form

I want to do edit on a modal pop up form, edit is working but cant see the existing instance, how I can do it? any help is appreciated.
Here I have passed the form as below
class DomainListView(ListView):
model = Domain
template_name = 'super_admin/domain_list.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = DomainEditForm(self.request.POST or None)
context['form'] = form
return context
and the template is as follows
<div class="modal fade" id="domain-edit-{{ item.pk }}">
<div class="modal-dialog" role="document">
<form class="form-valide" action="{% url 'domain_edit' item.pk %}" method="POST" id=""
enctype="multipart/form-data">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"> Edit Domain </h5>
<button type="button" class="close" data-dismiss="modal"><span>×</span>
</button>
</div>
<div class="modal-body">
<div class="basic-form">
<div class="form-group">
{% csrf_token %}
{{ form.errors }}
{{ form | crispy }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">submit</button>
</div>
</div>
</form>
</div>
</div>
this is inside for loop along with list items, I tried to fetch the instance as follows in get context data override, but it gives key error
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = get_object_or_404(Domain, kwargs={'pk': self.kwargs['pk']})
form = DomainEditForm(self.request.POST or None, instance=obj)
context['form'] = form
return context

I can't get the selected student in widget tweaks render_field using CreateView

I am using the following code in views.py:
class MatriculaCreateView(CreateView):
template_name = "website/matricula.html"
model = CursoPeriodoEstudante
form_class = MatriculaMembroForm
success_url = reverse_lazy("website:lista_estudantes")
def get_context_data(self, **kwargs):
context = super(MatriculaCreateView, self).get_context_data(**kwargs)
context['estudante'] = Estudante.objetos.filter(id=self.kwargs['pk'])
context['pk'] = self.kwargs['pk']
return context
I create the following in forms.py:
class MatriculaMembroForm(forms.ModelForm):
class Meta:
# Modelo base
model = CursoPeriodoEstudante
# Campos que estarão no form
fields = [
'estudante',
'cursoPeriodo'
]
And finally in the template I created this page:
{% extends "website/_layouts/base.html" %}
{% load widget_tweaks %}
{% block title %}Matricula de Membros{% endblock %}
{% block conteudo %}
<div class="container mt-5">
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Matrícula de Membros</h5>
<p class="card-text">
Complete o formulário abaixo para matricular
um <code>Membro</code> em um evento.
</p>
<p>Membro: {{ estudante }} </p>
<form method="post">
<!-- Não se esqueça dessa tag -->
{% csrf_token %}
<!-- Estudante -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Estudante</span>
</div>
{% render_field form.estudante class+="form-control" %}
</div>
<hr>
<!-- Curso -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Evento</span>
</div>
{% render_field form.cursoPeriodo class+="form-control" %}
</div>
<hr>
<div class="text-right">
Voltar
<button class="btn btn-primary">Enviar</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
The problem is, when the page opens, I want the field "Estudante" already filled with the one I selected in the view through the get_context_data (This field can be fixed). But the field always comes like this:printscreen from page. How can I fix to come with the student like this. What can I do? Thank you!
Ps.: I tried to put the following, but nothing happened...
class MatriculaCreateView(CreateView):
template_name = "website/matricula.html"
model = CursoPeriodoEstudante
form_class = MatriculaMembroForm
success_url = reverse_lazy("website:lista_estudantes")
def get_initial(self):
return {'estudante': Estudante.objetos.filter(id=self.kwargs['pk'])}
def get_context_data(self, **kwargs):
context = super(MatriculaCreateView, self).get_context_data(**kwargs)
context['estudante'] = Estudante.objetos.filter(id=self.kwargs['pk'])
context['pk'] = self.kwargs['pk']
return context
Override the get_initial() method of CreateView to set initial values for your model:
def get_initial(self):
return {'estudante': Estudante.objects.get(id=self.kwargs['pk'])}
I got it!
I should change the view to get, instead of filter (a query).
Thanks!

Django modelformset_factory deleting objects marked by can_delete

Hello I have got question I have made modelformset_factory and in options I have choosen can_delete = True and now I don't know how to delete marked objects as 'DELETE' : True to delete them from database. I was trying to do this in some ways and it didnt work. I was looking for it also in django formsetmodels documentation but this didnt help me. With this option can_delete = True I get additional checkbox in my html page Delete and marking him only prints me in console on print:
{'username': 'sw', 'email': 'a#gmail.com', 'city': 'ss', 'code': 12345, 'id': , 'DELETE': False}
Saving forms to database is working but I dont know how to delete marked forms from database.
I would be very thankful for every help.
I have made modelformset_factory from model in models.py
class TestModel(models.Model):
username = models.CharField(max_length=120)
email = models.EmailField()
city = models.CharField(max_length=120)
code = models.IntegerField()
#W admin panelu za miast TestModel object bedzie username
def __str__(self):
return self.username
Then I have added in my views.py function:
def django_modelformset(request):
TestModelFormset = modelformset_factory(TestModel, fields=['username', 'email', "city",
"code"], extra=1, can_delete=True)
formset = TestModelFormset(request.POST or None)
if formset.is_valid():
for form in formset:
print(form)
print(form.cleaned_data)
form.save()
context = {"formset": formset}
return render(request, "modelformset.html", context)
My modelformset.html looks like this:
<form method="POST" action="">
{% csrf_token %}
{{ formset.management_form}}
{% for form in formset %}
<div>
{{ form.as_p }}
<hr/>
</div>
{% endfor %}
<input type="submit" value="Save">
I haven't personally had to do this, but from the docs it seems you have a few options.
Call save on the formset instead of each form.
if formset.is_valid():
formset.save()
If you must loop through each form you could something like this.
if formset.is_valid():
for form in formset:
print(form.cleaned_data)
if form.cleaned_data["DELETE"]:
# Do what you want with the form data
# i.e. get the object from the database and delete it.
else:
form.save()
Loop through the deleted forms separately.
if formset.is_valid():
forms = formset.save(commit=False)
for object in formset.deleted_objects:
object.delete()
It's work for me
view.py
Blog_MetaFormSet = modelformset_factory(Metas, form=MetaForm, extra=0, can_delete=True)
Blog_MetaQuerySet = Metas.objects.filter(blog=blog_obj).order_by('created_at')
contex={
"blog_meta_formset": Blog_MetaFormSet(request.POST,queryset=Blog_MetaQuerySet),
}
if blog_meta_formset.is_valid():
for metaform in blog_meta_formset:
meta_obj = metaform.save(commit=False)
meta_obj.blog = blog_obj
if metaform.cleaned_data["DELETE"]==True:
meta_obj.delete()
else:
meta_obj.save()
In Templates
<div class="row">
<div id="cfield-form-list"> {{ blog_meta_formset.management_form }} {% for meta_form in blog_meta_formset %}
<div id="form-{{forloop.counter0}}" class="cfield-form xrow">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ meta_form.title|attr:"class:form-control"|attr:"type:text" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ meta_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ meta_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
</div>
</div> {{meta_form.id}} </div> {% endfor %} </div>
<div id="empty_form" class="hidden">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ blog_meta_formset.empty_form.title|attr:"type:text"|attr:"class:form-control" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ blog_meta_formset.empty_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ blog_meta_formset.empty_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
<div class="col-md-4">
<button type="button" class="btn btn-danger remove_cfield" rel="">Delete</button>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<button type="button" id="add-cfield" class="btn btn-primary mb-3 mt-3 ">Add Custom Field</button>
</div>
</div>
In js
const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
const addMoreBtn = document.getElementById('add-cfield')
addMoreBtn.addEventListener('click',add_new_form)
function add_new_form(event){
if (event){
event.preventDefault()
}
const currentCF_Forms = document.getElementsByClassName('cfield-form')
console.log(currentCF_Forms)
const currentCF_FormCount = currentCF_Forms.length //+ 1
const formCopyTarget = document.getElementById('cfield-form-list')
const copyEmptyFormEl = document.getElementById('empty_form').cloneNode(true)
//remove class hidden
copyEmptyFormEl.setAttribute('class','cfield-form xrow')
copyEmptyFormEl.setAttribute('id',`form-${currentCF_FormCount}`)
const regex = new RegExp('__prefix__','g')
copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex,currentCF_FormCount)
totalNewForms.setAttribute('value', currentCF_FormCount +1)
//now add new empty form element to our html form
formCopyTarget.append(copyEmptyFormEl)

Merge Login and Signup into one view in django

Merging login/signup view into one view, say LoginSignupView because I have login, signup form in one template.
I refered https://gist.github.com/jamesbrobb/748c47f46b9bd224b07fbut think that it doesn't work (Actually I don't know how it works)
My views.py :
from django.views.generic.base import ContextMixin, TemplateResponseMixin
from django.views.generic.edit import ProcessFormView
from django.http.response import HttpResponseRedirect, HttpResponseForbidden
from django.contrib.auth.forms import AuthenticationForm
from users.forms import MyUserCreationForm
class MultiFormMixin(ContextMixin):
form_classes = {}
prefixes = {}
success_urls = {}
grouped_forms = {}
initial = {}
prefix = None
success_url = None
def get_form_classes(self):
return self.form_classes
def get_forms(self, form_classes, form_names=None, bind_all=False):
return dict([(key, self._create_form(key, klass, (form_names and key in form_names) or bind_all)) \
for key, klass in form_classes.items()])
def get_form_kwargs(self, form_name, bind_form=False):
kwargs = {}
kwargs.update({'initial':self.get_initial(form_name)})
kwargs.update({'prefix':self.get_prefix(form_name)})
if bind_form:
kwargs.update(self._bind_form_data())
return kwargs
def forms_valid(self, forms, form_name):
form_valid_method = '%s_form_valid' % form_name
if hasattr(self, form_valid_method):
return getattr(self, form_valid_method)(forms[form_name])
else:
return HttpResponseRedirect(self.get_success_url(form_name))
def forms_invalid(self, forms):
return self.render_to_response(self.get_context_data(forms=forms))
def get_initial(self, form_name):
initial_method = 'get_%s_initial' % form_name
if hasattr(self, initial_method):
return getattr(self, initial_method)()
else:
return self.initial.copy()
def get_prefix(self, form_name):
return self.prefixes.get(form_name, self.prefix)
def get_success_url(self, form_name=None):
return self.success_urls.get(form_name, self.success_url)
def _create_form(self, form_name, klass, bind_form):
form_kwargs = self.get_form_kwargs(form_name, bind_form)
form_create_method = 'create_%s_form' % form_name
if hasattr(self, form_create_method):
form = getattr(self, form_create_method)(**form_kwargs)
else:
form = klass(**form_kwargs)
return form
def _bind_form_data(self):
if self.request.method in ('POST', 'PUT'):
return{'data': self.request.POST,
'files': self.request.FILES,}
return {}
class ProcessMultipleFormsView(ProcessFormView):
def get(self, request, *args, **kwargs):
form_classes = self.get_form_classes()
forms = self.get_forms(form_classes)
return self.render_to_response(self.get_context_data(forms=forms))
def post(self, request, *args, **kwargs):
form_classes = self.get_form_classes()
form_name = request.POST.get('action')
if self._individual_exists(form_name):
return self._process_individual_form(form_name, form_classes)
elif self._group_exists(form_name):
return self._process_grouped_forms(form_name, form_classes)
else:
return self._process_all_forms(form_classes)
def _individual_exists(self, form_name):
return form_name in self.form_classes
def _group_exists(self, group_name):
return group_name in self.grouped_forms
def _process_individual_form(self, form_name, form_classes):
forms = self.get_forms(form_classes, (form_name,))
form = forms.get(form_name)
if not form:
return HttpResponseForbidden()
elif form.is_valid():
return self.forms_valid(forms, form_name)
else:
return self.forms_invalid(forms)
def _process_grouped_forms(self, group_name, form_classes):
form_names = self.grouped_forms[group_name]
forms = self.get_forms(form_classes, form_names)
if all([forms.get(form_name).is_valid() for form_name in form_names.values()]):
return self.forms_valid(forms)
else:
return self.forms_invalid(forms)
def _process_all_forms(self, form_classes):
forms = self.get_forms(form_classes, None, True)
if all([form.is_valid() for form in forms.values()]):
return self.forms_valid(forms)
else:
return self.forms_invalid(forms)
class BaseMultipleFormsView(MultiFormMixin, ProcessMultipleFormsView):
"""
A base view for displaying several forms.
"""
class MultiFormsView(TemplateResponseMixin, BaseMultipleFormsView):
"""
A view for displaying several forms, and rendering a template response.
"""
class LoginSignupView(MultiFormsView):
template_name = 'users/login_signup.html'
form_classes = {'login': AuthenticationForm,
'signup': MyUserCreationForm}
success_url = '/'
def get_login_initial(self):
return {'email':'dave#dave.com'}
def get_signup_initial(self):
return {'email':'dave#dave.com'}
def get_context_data(self, **kwargs):
context = super(LoginSignupView, self).get_context_data(**kwargs)
context.update({"some_context_value": 'blah blah blah',
"some_other_context_value": 'blah'})
return context
def login_form_valid(self, form):
return form.login(self.request, redirect_url=self.get_success_url())
def signup_form_valid(self, form):
user = form.save(self.request)
return form.signup(self.request, user, self.get_success_url())
template : login_signup.html
{% extends 'chacha_dabang/skeleton/base.html' %}
{% load pipeline%}
{% block content %}
<div class="container">
<div id="loginbox" class="mainbox">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Sign In</div>
</div>
<div class="panel-body">
<div id="login-alert" class="alert alert-danger col-sm-12"></div>
<form id="loginform" class="form-horizontal" role="form" method="post" action="{% url 'users:login_signup' %}">
{% csrf_token %}
<!-- id / pw -->
<div class="input-group">
<span class="input-group-addon"><i class="icon-user"></i></span>
<input id="id_username" type="text" class="form-control" name="username" value="" placeholder="username">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input id="id_password" type="password" class="form-control" name="password" placeholder="password">
</div>
<div class="form-group">
<!-- Button -->
<div class="btn-controls">
<div class="row">
<input id="btn-login" class="btn btn-success" type="submit" name="login_submit" value="로 그 인" />
<a id="btn-fblogin" href="{% url 'social:begin' backend='facebook' %}" class="btn btn-primary col-xs-12"><i class="icon-facebook"></i> 1초만에 페이스북으로 로그인 </a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div class="signup">
아직 차차다방 회원이 아니세요? &nbsp
가입하기
</div>
<div class="forget">
비밀번호를 잊어버리셨나요?
</div>
</div>
</div>
</form>
</div> <!-- <div class="panel-body" > -->
</div> <!-- <div class="panel panel-info"> -->
</div> <!-- <div id="loginbox"> -->
<!-- Sign up Form -->
<div id="signupbox" class="mainbox">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Sign Up</div>
</div>
<div class="panel-body">
<form id="signupform" class="form-horizontal" role="form" method="post" action="{% url 'users:login_signup' %}">
{% csrf_token %}
<!-- signup -->
<div id="signupalert" class="alert alert-danger">
<p>Error:</p>
<span></span>
</div>
{{ forms.signup.as_p }}
<!--
<div class="form-group">
<label for="id_username" class="col-md-3 control-label"> 아이디: </label>
<div class="col-md-9">
{{ form.username }}
</div>
</div>
-->
<div class="form-group">
<!-- Button -->
<div class="btn-controls">
<div class="row">
<input id="btn-signup" class="btn btn-success" type="submit" name="signup_submit" value="가 입 하 기" />
<a id="btn-fblogin" href="{% url 'social:begin' backend='facebook' %}" class="btn btn-primary col-xs-12"><i class="icon-facebook"></i>1초만에 페이스북으로 로그인</a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div class="login">
이미 차차다방 회원이신가요? &nbsp
로그인하기
</div>
</div>
</div>
</form>
</div> <!-- <div class="panel-body"> -->
</div> <!-- <div class="panel panel-info"> -->
</div> <!-- <div id="signupbox"> -->
</div> <!-- <div class="container"> -->
{% endblock %}
{% block custom_js %}
{% javascript "account" %}
{% endblock %}
First, I test creating user (signup) but when I submit the button, it doesn't create new user.
What am I missing?
Your code is too much to go through, and has a lot of lines for a simple challenge. There are many options.
Create custom views instead of using Form Mixins. They would be a lot easier to write and understand. Identify the form submitted by a hidden input in each form.
Create 2 views using the Mixins, each for login and signup and modify the action part of your forms to submit to the correct view respectively.
Hope it helps.

Crispy-forms form.name renders rubbish

I'm trying to render a form but the {{form.name}} renders rubbish. The problem is that I can't even debug this to figure where the thing gets crooked.
The form:
class ActionItemForm(forms.ModelForm):
class Meta:
model = ActionItem
fields = ('project', 'portfolio', 'name', 'description', 'resolution', 'parent', 'priority', 'status', 'assignee', 'due_date')
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout()
super(ActionItemForm, self).__init__(*args, **kwargs)
The view:
def action_item_actions(request, action_item_id, action_code):
def enrich_form(wf_item, form):
form.id = 'edit_action_item'
form.name = form.id
form.title = wf_item.name
form.action = '/forms/action_item/edit/%s' % action_item_id
return form
action_item = ActionItem.objects.get(id=action_item_id)
wf_item = action_item.wf_get_action_by_code(action_code)
if wf_item:
if wf_item.trans_to:
form = ActionItemForm(instance=action_item, initial={action_item.get_wf_field(): type(getattr(action_item, action_item.get_wf_field())).objects.get(id=wf_item.trans_to)})
else:
form = ActionItemForm(instance=action_item)
form = enrich_form(wf_item, form)
for field in form.Meta.fields:
if field not in wf_item.fields:
form.helper.layout.fields.append(Field(field, type='hidden'))
return render_to_response('forms/modal_form.html', {'form': form}, template.RequestContext(request))
else:
return render_to_response('forms/message.html', {'message': Message('Error', 'WF Descriptor not found')}, template.RequestContext(request))
When the form exists the view, the form.name is correct:
Now when the form enters the template, it's still ok:
The view is quite simple:
{% load crispy_forms_tags %}
<form id="{{ form.id }}" role="form" class="small" name="{{ form.name }}">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">{{ form.title }}</h4>
</div>
<div class="modal-body">
{% crispy form %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="button" class="btn btn-primary" value="Save" id="" onclick="submit_form('{{ form.id }}','{{ form.action }}')">
</div>
</div>
</div>
</form>
However, the form tag is rendered as this:
<form id="edit_action_item" role="form" class="small" name="<input id="id_name" maxlength="256" name="name" type="text" value="Test action item" />">
How can I track down where this gets broken? I kind of suspect that it gets broken because form may be potentially mixing the 'name' field with the form.name attribute.
You have field name in your form. So {{ form.name }} returns output for field name. You can put form name to other variable in __init__:
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout()
super(ActionItemForm, self).__init__(*args, **kwargs)
self.form_name = self.name # this line added
and call {{ form.form_name }} in template
<section class="form">
<h5>Contact Form</h5>
<h6>Let Us Know</h6>
<form action="{% url 'web:contact' %}" method="post" class="ajax">
{% csrf_token %}
<p class="left">
<label for="{{form.name.label.id_for_label}}">
{{form.name.label}}
{% if form.name.field.required %}
<small class="star">*</small>
{% endif %}
</label>
{{form.name}}
{% if form.name.errors %}
<span class="error">{{form.name.errors.as_text}}</span>
{% endif %}
</p>
</form>
</section>