How to direct a page from a form Django - python

I am working on a dictionary app, i am allowing a user to enter a word through a form. When the word is entered in the form and a submit button is pressed i want the form to be maintained on the same page however when the user enter the word and presses submit the form disappears leaving only the submit button and the search results
Here is the dictionary/form code
class NameForm(forms.Form):
your_name = forms.CharField(max_length=100, label=False)
the dictionary/view code
def index(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
word = form.cleaned_data['your_name']
print(word)
if Dictionary.get_verb(word):
verb = Dictionary.get_verb(word)
else:
verb = False
print(verb)
if Dictionary.get_noun(word):
noun = Dictionary.get_noun(word)
else:
noun = False
print(noun)
synonyms = Dictionary.get_synonyms(word)
print(synonyms)
form = NameForm()
context = {
'verb':verb,
'noun':noun,
'synonyms':synonyms,
}
return render(request,'index.html' ,context)
else:
form = NameForm()
context = {
'form': form,
}
return render(request, 'index.html', context)
and the index.html
form action="" method="post">
{% csrf_token %}
{{form}}
<br>
<input type="submit" value="Submit">
</form>
<hr>
{% if noun %}
<h2>Noun</h2>
{% for noun_word in noun %}
<p>{{noun_word}}</p>
{% endfor %}
{% else %}
<!-- print nothing-->
{% endif %}
<br>
<hr>
{% if verb %}
<h2>Verb</h2>
{% for verb_info in verb %}
<p>{{verb_info}}</p>
{% endfor %}
{% else %}
<!-- print nothing-->
{% endif %}
<h2>Synonyms</h2>
{% if synonyms %}
{% for synonym_info in synonyms %}
<p>{{synonym_info}}</p>
{% endfor %}
{% else %}
<!-- print nothing-->
{% endif %}
I have created a dictionary class to interact with the Dictionary API. But my challenge is how do i go about it so that when the form is submitted it will return the form and the button together with the results below. Thank you!!

you are missing the form in context when the form is valid, that's why it is disappearing.
form = NameForm()
context = {
'verb': verb,
'noun': noun,
'synonyms': synonyms,
'form': form ## missing this (add)
}
return render(request,'index.html' ,context)

You can add render in forms.py or you can set the action in your template
<form class="postForm" action="{% url 'name of your url' %}" method="POST">

Related

save check box to Boolean field in django using hand written form

Hi trying to save checkbox value on submit. The form displays the value correct. When value is True is, its checked and when false its unchecked. However I just can't get it to save on POST.
views.py
#login_required(login_url='login') def engine(request):
eng= Player.objects.filter(customer=request.user.customer)
isa= Customer.objects.filter(name=request.user.customer)
if request.method == "POST":
customer=request.user.customer
isa =
Customer.objects.filter(name=request.user.customer)
.update(is_active=request.POST.get('is_active'))
isa.save()
return redirect('engine')
context= {'eng': eng, 'isa': isa}
return render(request, 'base/engine.html', context)
engine.html
{% csrf_token %}
{% for k in isa %}
<label>ON/OFF</label>
<input type="checkbox" id="is_active" name="is_active" {% if
k.is_active == 1 %} checked{% endif %}>
<input type="submit" value="save" />
{% endfor %}
</form>

Editing view for combined form and inline_formset

I have been trying to create an editing view that allows me manage both parent and child models using an inline formset based in the documentation here
From what I can appreciate the formset doesn't validate. I did try and change it so that instead of validating the entire formset it iterated through each individual form in the formset and validated them individually. This did allow me to add items to the formset but not delete them.
At the moment the code results in "didn't return an HttpResponse object. It returned None instead" value error as the redirect is in the If valid statement and so if that does not result in true there is no other redirect to fall back on.
Models
class Shoppinglist(models.Model):
name = models.CharField(max_length=50)
description = models.TextField(max_length=2000)
created = models.DateField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name='lists', on_delete=models.CASCADE)
last_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=80, unique=True)
amount = models.IntegerField(default=1)
shoppinglist = models.ForeignKey(Shoppinglist, on_delete=models.CASCADE)
def __str__(self):
return self.name
URL
urlpatterns = [
url(r'^shoppinglists/(?P<pk>\d+)/edit/$', views.shoppinglist_edit, name='shoppinglist_edit'),
]
View
def shoppinglist_edit(request, pk):
try:
shoppinglist = Shoppinglist.objects.get(pk=pk)
except ShoppingList.DoesNotExist:
raise Http404
ItemInlineFormset = inlineformset_factory(Shoppinglist, Item, extra=1, fields=('name', 'amount'))
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
Template
{% block content %}
<form method="post">
{% csrf_token %}
<label>List Name</label>
{{ listform.name }}
{% if listform.first_name.errors %}
{% for error in listform.first_name.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<label>Description</label>
{{ listform.description }}
{% if listform.description.errors %}
{% for error in listform.description.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
{{ formset.management_form }}
{% for form in formset %}
<div class="item-formset">
{{ form.amount }}
{% if form.amount.errors %}
{% for error in form.amount.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
{{ form.name }}
{% if form.name.errors %}
{% for error in form.name.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<div class="row spacer">
<button type="submit" class="btn btn-block btn-primary">Create</button>
</div>
</form>
{% endblock %}
{% block extra_js %}
<script>
$('.item-formset').formset({
addText: 'add item',
deleteText: 'remove'
});
</script>
{% endblock %}
Please note I am using this jquery plugin in the template.
https://github.com/elo80ka/django-dynamic-formset
it is probably either your form or formset is invalid, and you dont use else statement to handle that.
so in your views.py:
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
# either your form or formset is invalid, so this code will render it again.
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
or you can simplify it with this:
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
# notice the indentation
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
Mentioned error coming because you write this return render(request, 'edit_list_with_items.html', context) inside else block.
instead of this:
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'
}
return render(request, 'edit_list_with_items.html', context)
Do this:
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
}
return render(request, 'edit_list_with_items.html', context)

Showing error messages in template in DefaultUserCreationForm - django

I am having a problem in displaying an error message in the HTML page. I am using Django's default UserCreationForm for signup page. It has two password fields - one original and one for confirmation. When the user enters different passwords, I am getting at /signup/ whereas I want the error message to be displayed in the HTML page saying that the passwords didn't match. I have gone through the docs and I have added some related lines in my code, I don't know where I'm going wrong.
Here is my views.py:
def adduser(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
print(request.POST)
if(form.is_valid):
try:
user = employees.objects.get(emp_id=request.POST['username'] )
except employees.DoesNotExist:
user = None
print(user)
if( user != None ):
if request.POST['username'] in employees.objects.values_list('manager_id__emp_id',flat=True):
g = Group.objects.get(name='Managers')
newuser = form.save()
newuser.groups.add(g)
else:
g = Group.objects.get(name='Employees')
newuser = form.save()
newuser.groups.add(g)
return render(request,'login.html',{'form': form})
else:
form = UserCreationForm()
return render(request,'signup.html', {'form': form, 'msg': 'Enter valid employee id'})
else:
form = UserCreationForm()
return render(request,'signup.html', {'form': form})
and here is my signup.html:
<body>
<div class="container">
<div class="page-header">
<h1>Sign-up Here</h1>
</div>
{% block body %}
<form method="post">
{% csrf_token %}
<font color="orange" size="5px"><p> * Enter your Employee id, as username * </p></font>
{{ form.as_p }}
<font color="red"> {{ msg }} </font><br>
<font color="red"> {{ form.password1.errors }} </font><br>
<font color="red"> {{ form.password2.errors }} </font><br>
<br>
<button class="btn btn-success" type="submit"> Go! </button>
</form>
{% endblock %}
</div>
</body>
The problem is in this line :
if(form.is_valid):
This is not the correct way of testing form validation,
instead use:
if form.is_valid():
Also you dont need to declare form multiple times,it can be done single time.
Like this :
def adduser(request):
form = UserCreationForm(request.POST or None)
if request.method == 'POST':
print(request.POST)
if form.is_valid():
try:
user = employees.objects.get(emp_id=request.POST['username'] )
except employees.DoesNotExist:
user = None
print(user)
if( user != None ):
if request.POST['username'] in employees.objects.values_list('manager_id__emp_id',flat=True):
g = Group.objects.get(name='Managers')
newuser = form.save()
newuser.groups.add(g)
else:
g = Group.objects.get(name='Employees')
newuser = form.save()
newuser.groups.add(g)
return render(request,'login.html',{'form': form})
else:
form = UserCreationForm()
return render(request,'signup.html', {'form': form, 'msg': 'Enter valid employee id'})
return render(request,'signup.html', {'form': form})
And there can be diffrenmt type of erros, field and non_field_errors, so use someting like this :
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}

How to use multiple forms with a Form Wizard form in the same template (Django)

I'm using multiple forms in the same template and they all work until I add my Form Wizard, when it becomes that either the FormWizard - form works or the rest of the forms works but not both simultaniousely.
When I have the URL's with postid (?P\d+) -url placed prior to the ContactWizard.as_view -urls the forms in the view - function one_labeling are displayed but not the Form Wizard/ContactWizard.as_view in views.py class ContactWizard(SessionWizardView)
url(r'^label$', LabelingIndex),
url(r'^label(?P<postID>\d+)$',one_labeling),# <----- here
url(r'^label',ContactWizard.as_view([Form1, Form2, Form3])),
url(r'^label(?P<one_labeling>\d+)/$', 'formwizard.views.one_labeling'),
and vice versa, when the URL's for the Form Wizard is placed before the postID - url for the forms in the view function one_labeling then the FormWizard is displayed (and works) but the other forms aren't displayed/evoked.
url(r'^label$', LabelingIndex),
url(r'^label',ContactWizard.as_view([Form1,Form2, Form3])),
url(r'^label(?P<one_labeling>\d+)/$', 'formwizard.views.one_labeling'),
url(r'^label(?P<postID>\d+)$',one_labeling), #<----- here
I'm not sure on how to prefix the Wizard Form so that I could use it as {{ form9.as_p }} like with {{ form3.as_p }} instead of {{ form1 }}{{ wizard.management_form }} or {{ form }} in the done.html below, so that it would work simultaniousely with the other forms in template one_labeling_index.html.
in template done.html
{% extends 'base_one_labeling.html' %}
{% block content %}
{% for form in form_data %}
{{ form }}
{% endfor %}
{% endblock %}
in views.py
class ContactWizard(SessionWizardView):
template_name = "one_labeling_index.html"
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]
logr.debug(form_data[0]['subject'])
logr.debug(form_data[1]['sender'])
logr.debug(form_data[2]['message'])
send_mail(form_data[0]['subject'],form_data[1]['sender'],
form_data[2]['message'], 'xxxx#gmail.com',
fail_silently=False)
return form_data
in views.py,LabelingIndex,function evoking template labeling_index.html
def LabelingIndex(request):
#labelings, objects in class Labeling() in models.py
labelings = Labeling.objects.all()
c ={"labelings":labelings}
c.update(csrf(request))
return render(request,"labeling_index.html", c)
in views.py,one_labeling, views function one_labeling
def one_labeling(request,postID):
#one_labeling, object in class Labeling
one_labeling= Labeling.objects.get(id=postID)
template = one_labeling_index.html
if request.method == "POST":
# forms used in one_labeling_index.html
form = SentenceForm(request.POST, prefix="sentence")
form2 = OpenFileForm(request.POST, prefix="file")
form3 = LabelingForm(request.POST,prefix="form3")
form9 =LabelingForm2(request.POST,prefix="labeling")
if form.is_valid() and 'button1' in request.POST:
# do ....
if form3.is_valid() and 'button2' in request.POST:
post_one_labeling(request.POST, one_labeling)
else:
form = SentenceForm()
form2 = OpenFileForm()
form3 = LabelingForm()
form9 = LabelingRRGForm2()
c = {"one_labeling":one_labeling,"form3":form3,"form":form,"form9":form9...... }
c.update(csrf(request))
return render(request,template,c,context_instance=RequestContext(request))
in template Labeling_index.html
{% for one_labeling in labelings %}
# Link to new id (postid) - page; template one_labeling.html
&nbsp Subject: <a href="/label{{ one_labeling.id }}">{{ one_labeling.title }}<a/><br/>
{% endfor %}
in template one_labeling_index.html
# extending base_one_labeling.html
{% extends "base_one_labeling.html" %}
{% block content %}
# form3
<form3 action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form3.as_p }}
</form3>
# Form Wizard
<p>Label {{ wizard.steps.step1 }} out of {{ wizard.steps.count }} ({{ wizard.steps.step1 }}/{{ wizard.steps.count }})</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form1 in wizard.form.forms %}
{{ form1 }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
{% endif %}
<html>
<body>
The line
url(r'^label',ContactWizard.as_view([Form1, Form2, Form3])),
matches any url beginning by "label", so any of your other url you put after are never matched.
Also, except the trailing "/", the lines:
url(r'^label(?P<one_labeling>\d+)/$', 'formwizard.views.one_labeling'),
url(r'^label(?P<postID>\d+)$',one_labeling), #<----- here
match the same thing.
So you have to order carefully your urls, and distinguish them somehow to avoid any ambiguity.

How to properly overwrite clean() method

I'm trying the Tango With Django Tutorial and the overwrite in the clean() method isn't working to add 'http://' in my urls. What is wrong in this code?
forms.py
class PageForm(forms.ModelForm):
...
def clean(self):
cleaned_data = self.cleaned_data
url = cleaned_data.get('url')
if url and not url.startswith('http://'):
url += 'http://'
cleaned_data['url'] = url
return cleaned_data
views.py
def add_page(request, category_name_slug):
try:
cat = Category.objects.get(slug=category_name_slug)
except Category.DoesNotExist:
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit=False)
page.category = cat
page.views = 0
page.save()
return category(request, category_name_slug)
else:
print(form.errors)
else:
form = PageForm()
context_dict = {'category': cat, 'form': form}
return render(request, 'rango/add_page.html', context_dict)
add_page.html
{% extends "base.html" %}
{% block title %}Add Page{% endblock title %}
{% block content %}
<h1>Add a Page</h1>
<form id='page_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 %}
<input type="submit" name="submit" Value="Create Page" />
</form>
{% endblock content %}
The admin is working properly, but the html itself isn't accepting this writing.
Usually, since you are cleaning only one field, you should do this in a field-specific method clean_url.
def clean_url(self):
url = self.cleaned_data['url']
# your cleaning here
return url
you need this:
def clean(self):
cleaned_data = super(PageForm, self).clean() # <-----------
url = cleaned_data.get('url')
if url and not url.startswith('http://'):
url += 'http://'
cleaned_data['url'] = url
return cleaned_data

Categories

Resources