django wizard form problem in showing multiforms - python

My Views Page:
from django.shortcuts import render
from django.http import HttpResponse
from formtools.wizard.views import SessionWizardView
from .forms import ContactForm1,ContactForm2,ContactForm3
class ContactWizard(SessionWizardView):
template_name = 'contact.html'
form_list = [ContactForm1,ContactForm2]
def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)
return render_to_response('done.html', {'form_data': form_data})
def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]
return form_data
My form page:
from django import forms
class ContactForm1(forms.Form):enter code here
subject = forms.CharField(max_length=100)
class ContactForm2(forms.Form):
sender = forms.EmailField()
class ContactForm3(forms.Form):
message = forms.CharField(widget=forms.Textarea)
I am new to Django I am working with the wizard forms but this wizard form not showing the if statement of the wizard multiform. Please help me to solve the wizard form.
Html Page
{% load i18n %}
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="/contact/" method="post">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% 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>
Help to find out the problem in wizard multiform

Related

List with checked checkboxes in Django

So, i want to get the checked checkboxes items ids as a list and show them on another page. But when i get to that specific page i get the value 'None' instead of the list of ids. What could go wrong? I tried some different versions from another questions already posted on the site, but the result was the same.
Here is the code:
models.py:
from django.db import models
class afirmatii(models.Model):
text = models.CharField(max_length = 250)
def __str__(self):
return self.text
views.py:
def exam(request):
if request.method == 'POST':
checks = request.POST.get('selected[]')
request.session['checks2'] = checks
context = {
'title' : 'Title1',
'aff': afirmatii.objects.order_by('id')
}
return render(request, 'pages/exam.html', context)
def result(request):
checks = request.session.get('checks2')
context = {
'title' : 'Title2',
'checks': checks
}
return render(request, 'pages/result.html', context)
exam.html:
{% extends "./base.html" %}
{% block content %}
<div class="text-break">
<form action="{% url 'result' %}" method="POST">
{% csrf_token %}
{% for q in aff %}
<div class="border mb-3 rounded-sm bg-light p-2">
<div class="custom-control custom-checkbox checkbox-info">
<input type="checkbox" class="custom-control-input" id="{{ q.id }}" name = "selected[]">
<label class="custom-control-label" for="{{ q.id }}" name = 'selected[]'> {{ q.text }} </label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-md btn-outline-info">Next</button>
</form>
</div>
{% endblock content %}
result.html:
{% extends "./base.html" %}
{% block content %}
<body>
<div class="text-center">
<p class="pb-5"> {{ checks }} </p><br>
<div class="row">
<div class="col">
Home
</div>
<div class="col">
Learn more
</div>
</div>
</div>
</body>
{% endblock content %}
You can try use FORMSETS A formsets is a layer of abstraction to work with multiple forms on the same page.
You can paint the list of questions according to records in the table and get ids (or other fields) of the marked answers
forms.py
class ExamForm(forms.Form):
checkbox = forms.BooleanField(required=False)
id = forms.CharField(widget=forms.HiddenInput)
text = forms.CharField(widget=forms.HiddenInput)
views.py
from django.shortcuts import render
from django.forms import formset_factory
from .forms import *
def exam(request):
aff = afirmatii.objects.order_by('id')
exam_formset = formset_factory(ExamForm, extra=0)
formset = exam_formset(initial=[{'id': x.id, 'text': x.text} for x in aff])
checks = []
if request.method == 'POST':
formset = exam_formset(request.POST)
if formset.is_valid():
for form in formset.forms:
if form.cleaned_data.get('checkbox', None):
checks.append(form.cleaned_data)
context = {
'formset': formset,
'checks': checks,
}
return render(request, 'pages/exam.html', context)
exam.html
{% if not checks %}
<h1>Exam:</h1>
<form action="{% url 'exam' %}" method="POST">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset.forms %}
<div class="form-group">
{{ form.checkbox }}
{{ form.text.value }}
{{ form.id }}
{{ form.text }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% else %}
<h1>Results:</h1>
{% for check in checks %}
<p>{{ check.id }} {{ check.text }}</p>
{% endfor %}
{% endif %}

Custom Django FormWizard Steps with Templates

This is my working FormWizard that I made by following this and this
views.py
from django.shortcuts import render
from django.template import RequestContext
from django.http import HttpResponseRedirect
from formtools.wizard.views import SessionWizardView
# Create your views here.
def index(request):
return render(request, 'wizardApp/index.html')
class ContactWizard(SessionWizardView):
template_name = "wizardApp/contact_form.html"
def done(self, form_list, **kwargs):
process_form_data(form_list)
return HttpResponseRedirect('../home')
def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]
print(form_data[0]['subject'])
print(form_data[0]['info1'])
print(form_data[0]['info2'])
print(form_data[1]['sender'])
print(form_data[1]['info1'])
print(form_data[1]['info2'])
print(form_data[2]['message'])
print(form_data[2]['info1'])
print(form_data[2]['info2'])
return form_data
urls.py
from django.conf.urls import url
from wizardApp import views
from wizardApp.forms import ContactForm1, ContactForm2, ContactForm3
from wizardApp.views import ContactWizard
app_name = 'wizardApp'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^home/$', views.index, name='index'),
url(r'^admin/', admin.site.urls),
url(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2, ContactForm3])),
]
forms.py
from django import forms
class ContactForm1(forms.Form):
subject = forms.CharField(max_length=100)
info1 = forms.CharField(max_length=100)
info2 = forms.CharField(max_length=100)
class ContactForm2(forms.Form):
sender = forms.EmailField()
info1 = forms.CharField(max_length=100)
info2 = forms.CharField(max_length=100)
class ContactForm3(forms.Form):
info1 = forms.CharField(max_length=100)
info2 = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
contact_form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
{{ wizard.form.media }}
</head>
<body>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="/contact/" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">first step</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">prev step</button>
{% endif %}
<input type="submit" value="submit"/>
</form>
</body>
</html>
I am having a lot of trouble understanding how customizing each step of the form works. There is very little help out there for this unfortunately. I saw this post about creating multiple templates and that kind of helps, but my main disconnect is on how i create those templates and how they are implemented in each step.
In a normal form i can do something like this
<form novalidate="novalidate" autocomplete="on" method="POST">
{% csrf_token %}
<div class="form-horizontal">
<div class="form-left">
{{form.first_name}}
{{form.first_name.errors}}
</div>
<div class="form-right">
{{form.last_name}}
{{form.last_name.errors}}
</div>
</div>
<div>
{{form.email}}
{{form.email.errors}}
</div>
<div>
<input type="submit" value="Submit">
</div>
</form>
How do i access each individual field? Where i can add in html and other bits to help with general styling? How should i go about making one of these for each steps? Should i basically be copy and pasting the html and everything into other "templates"? How do i call each template for each step?
Thanks!
Hope you figured it out. For the sake of anyone who runs into this, this is how I solved this. I replaced {{ wizard.form }} with a for loop to manually render the inputs:
<form action="/contact/" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{% for field in wizard.form %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
<span class="message">{{ field.errors }}</span>
{% endfor %}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">first step</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">prev step</button>
{% endif %}
<input type="submit" value="submit"/>
You can create a template for each of your forms and then associate it to its corresponding form as described in the docs or if you want each form to use the same template, all you need to do is set your template_name attribute in your ContactWizard class:
class ContactWizard(SessionWizardView):
template_name = "contact_form.html"

Got this UnboundLocalError at /nesting/ local variable 'content' referenced before assignment

I want to display the necessary field errors when the user who is populating the form does not enter valid information into the forms.
However, each I time I test the error script by clicking the submit button without populating any of the fields I get this error :
UnboundLocalError at /nesting/ local variable 'content' referenced
before assignment
How do I correct this?
This is my code :
veiws.py
from django.shortcuts import render, redirect
from django.views.generic import TemplateView
from nesting.forms import Identity_form
from nesting.models import Identity_unique
class Identity_view(TemplateView):
template_name = 'nesting/nesting.html'
def get(self, request):
form = Identity_form()
Identities = Identity_unique.objects.filter(user = request.user)
var = {'form': form, 'Identities': Identities}
return render(request, self.template_name, var)
def post(self, request):
form = Identity_form(request.POST or None)
if form.is_valid():
NIS = form.save(commit = False)
NIS.user = request.user
NIS.save()
content = form.cleaned_data['NIS']
form = Identity_form()
return redirect('nesting:nesting')
var = {'form': form, 'content': content}
return render(request,self.template_name, var)
The error messages is saying the error is caused by this line
var = {'form': form, 'content': content}
return render(request,self.template_name, var)
nesting.html
{% extends 'base.html' %}
{% load widget_tweaks %}
<html>
<head>
{% block head %}
<title>nesting</title>
{% endblock %}
</head>
<body>
{% block body %}
<div class = "container" style = "margin-top: 80px;">
<form method = 'post' novalidate>
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
<div class = "col-sm-8 col-md-8 col-lg-6">
<p class = "font-weight-bold">Create Patient</p>
{% if form.non_field_errors %}
<div class = "alert alert-danger" role = "alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class = "form-group">
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class = "invalid-feedback ">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class = "form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<button class = "btn-primary btn-large btn ">Submit</button>
</div>
</form>
</div>
<div class = "col-sm-8 col-md-6 col-lg-6">
{% for Identity in Identities %}
<div class = "card" style = "margin-top: 40px;">
<div class = "card-header">
<p class="font-weight-bold"> {{Identity.First_Name}} {{Identity.Last_Name}} </p>
</div>
<div class = "card-body">
<div class = "card-title">
<p class = "font-weight-light" style = "font-family: Optima">National Insurance Scheme : {{ Identity.NIS }}</p>
</div>
<p><small class = "card-text">Created On : {{ Identity.Timestamp }}</small></p>
<p><small class = "card-text">Address : {{ Identity.Residence }}</small></p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
</body>
</html>
In your views. content is referenced in var = {'form': form, 'content': content}. It is only instantiated after if form.is_valid() block.
The unboundError occurs when your form is invalid, then the var = {'form': form, 'content': content} does not have any variable named content to refer to.
The Fix: instantiate content before the if form.is_valid() block.
content = None

Display form fields one at a time in template-django

I have set of questions and its answers stored in db.I have a form to get answer for each question.I need to display only one question at a time in template and validate that answer against the original answer stored in db.
For now am able to display one value.But what i need is to display a question in a page and validate if the answer is correct,move on to display next question from db and so on. How do I achieve this?
form.py
from django import forms
class details_form(forms.Form):
answer = forms.CharField(widget=forms.TextInput())
views.py
def display_question(request):
context = RequestContext(request)
if request.method == 'GET':
print "GET"
form_class = details_form()
que_data = details.objects.get(que_id=1)
else:
##POST request
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data},context)
template:
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action='/next'>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
Update:
views.py
def display_question(request,question_id):
context = RequestContext(request)
form_class = details_form()
try:
quesno_id = {'id':question_id}
que_data = details.objects.get(que_id=question_id)
except details.DoesNotExist:
pass
if request.method == 'POST':
form = details_form(request.POST)
if form.is_valid():
user_answer = form.cleaned_data['answer']
if que_data.original_answer == user_answer:
return HttpResponseRedirect("question/%s/" %question_id+1)
else:
print form.errors
else:
pass
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data,'quesno_id':quesno_id},context)
template
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question {{ quesno_id.id}} : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action="/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
urls.py
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^question/(?P<question_id>\w+)/$',views.display_question,name='display_question'),
)
models.py
from django.db import models
class Songdata(models.Model):
que_id = models.AutoField(primary_key=True)
que = models.CharField(max_length=256)
original_answer = models.TextField()
def __unicode__(self):
return self.song_name
form.py
from django import forms
class details_form(forms.Form):
user_answer = forms.CharField(widget=forms.TextInput())
You need to use an absolute URL path like HttpResponseRedirect("/question/%s/" % (question_id+1)) (notice the leading slash)

Issues with forms.py

when I am submitting the form, I am getting KeyError at password1 in forms.py line 25 password1=self.cleaned_data['password1']. The code of files is given below:
The code of forms.py is:
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from drinker.models import Drinker
class RegistrationForm(ModelForm):
username = forms.CharField(label=(u'User Name'))
email = forms.EmailField(label=(u'Email Address'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
password1 = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))
class Meta:
model=Drinker
exclude=('user',)
def clean_username(self):
username=self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("The Username is already taken, please try another.")
def clean_password(self):
password=self.cleaned_data['password']
password1=self.cleaned_data['password1']
if password != password1:
raise forms.ValidationError("The Password did not match, please try again.")
return password
The code of html file is:
{% extends "base.html" %}
{% block extrahead %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js" type="text/javascript"></script>
<script>
$(function() {
$( "#id_birthday" ).datepicker();
});
</script>
{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{% if form.errors %}<p>Please correct the following fields:</p>{% endif %}
<div class="register_div">
{% if form.username.errors %}<p class="error">{{ form.username.errors }}</p>{% endif %}
<p><label for="username"{% if form.username.errors %} class="error"{% endif %}>Username:</label></p>
<p>{{ form.username }}</p>
</div>
<div class="register_div">
{% if form.email.errors %}<p class="error">{{ form.email.errors }}</p>{% endif %}
<p><label for="email"{% if form.email.errors %} class="error"{% endif %}>Email:</label></p>
<p>{{ form.email }}</p>
</div>
<div class="register_div">
{% if form.password.errors %}<p class="error">{{ form.password.errors }}</p>{% endif %}
<p><label for="password"{% if form.password.errors %} class="error"{% endif %}>Password:</label></p>
<p>{{ form.password }}</p>
</div>
<div class="register_div">
{% if form.password1.errors %}<p class="error">{{ form.password1.errors }}</p>{% endif %}
<p><label for="password1"{% if form.password1.errors %} class="error"{% endif %}>Password1:</label></p>
<p>{{ form.password1 }}</p>
</div>
<div class="register_div">
{% if form.birthday.errors %}<p class="error">{{ form.birthday.errors }}</p>{% endif %}
<p><label for="birthday"{% if form.birthday.errors %} class="error"{% endif %}>Birthday:</label></p>
<p>{{ form.birthday }}</p>
</div>
<div class="register_div">
{% if form.name.errors %}<p class="error">{{ form.name.errors }}</p>{% endif %}
<p><label for="name"{% if form.name.errors %} class="error"{% endif %}>Name:</label></p>
<p>{{ form.username }}</p>
</div>
<p><input type="submit" value="submit"/></p>
</form>
{% endblock %}
the view file is
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User
from django.shortcuts import render_to_response
from drinker.models import Drinker
from django.template import RequestContext
from drinker.forms import RegistrationForm
def DrinkerRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
#return render_to_response('register')
form = RegistrationForm(request.POST)
if form.is_valid():
user=User.objects.create_user(username=form.cleaned_data['username'], email=form.cleaned_data['email'], password = form.cleaned_data['password'])
user.save()
# drinker=user.get_profile()
# drinker.name=form.cleaned_data['name']
# drinker.birthday=form.cleaned_data['birthday']
# drinker.save()
drinker=Drinker(user=user,name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
drinker.save()
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html',{'form':form} , context_instance=RequestContext(request))
else:
''' user is not submitting the form, show them a blank registration form '''
form = RegistrationForm()
context={'form':form}
return render_to_response('register.html',context , context_instance=RequestContext(request))
Django calls clean_xxx() methods for each field in the form. When a field is valid, it will add the key/value to cleaned_data. When Django calls clean_password and it has not yet processed the field password1 then cleaned_data won't contain a key/value pair for password1. That is the error you are currently getting.
To fix it, you need to move the validation of the passwords to clean() which is called after Django has checked each of the field individually. This method can be used to perform validation which concerns multiple fields of the form (i.e., the form as a whole).
This also makes sense because the error you want to raise is about the mismatch between password and password1, not just the field password (the field that you are currently cleaning).

Categories