I've got a problem with django with handling forms : I created a form with 2 fields, and I associated it to my view, but it tells me that my fields are undefined. Could you explain me please ?
I created a form in my index.html :
<form action="/addUser" method="post">
{% csrf_token %}
<label> Name of the Employee : <input type="text" name="employeeName", id="employeeName"/> </label>
<label> Email of the Employee : <input type="email" name="employeeEmail", id="employeeEmail" /> </label>
<button class="btn btn-primary" type="submit">Add User</button>
</form>
Then I created in views.py
def addUser(request):
if request.method == 'POST':
form = CreationUserForm(request.POST)
newEmployee = Employee()
newEmployee.name = form[employeeName]
newEmployee.email = form[employeeEmail]
newEmployee.save()
return HttpResponseRedirect(reverse('app:home'))
And then I created in forms.py
class CreationUserForm(forms.Form):
employeeName = forms.CharField(label='employeeName', max_length=254)
employeeEmail = forms.CharField(label='employeeEmail', max_length=254)
So I don't understand why I get this error : name 'employeeName' is not defined
For my point of view it is...
I tried with form.employeeName too, but it considered as a non existant attribute.
Thank you for helping :)
In your addUser method, both the employeeName and employeeEmail are variables, which are not defined. You want to be accessing the keys via the strings.
def addUser(request):
if request.method == 'POST':
form = CreationUserForm(request.POST)
newEmployee = Employee()
newEmployee.name = form['employeeName']
newEmployee.email = form['employeeEmail']
newEmployee.save()
return HttpResponseRedirect(reverse('app:home'))
also a Django suggestion - before accessing the attributes of the form, it is often useful to check that the input is valid by calling if form.is_valid() as defined here: https://docs.djangoproject.com/en/2.2/ref/forms/api/
Related
This question already has an answer here:
Why form is not valid in django
(1 answer)
Closed 8 months ago.
In my views.py my have a view where a user can create a post with a title, media file and caption.
When i check if form.is_valid(): it always returns as false and i cannot see the issue with my form.
views.py
def your_profile(request):
if request.method == "POST":
form = CreatePost(request.POST)
if form.is_valid():
title = form.cleaned_data.get("title_input")
media = form.cleaned_data.get("media_input")
caption = form.cleaned_data.get("caption_input")
context = {"title": "Your Profile"}
return render(request, "myApp/your_profile.html", context)
forms.py
class CreatePost(forms.Form):
title = forms.CharField(max_length=30)
media = forms.FileField(max_length=350)
caption =forms.CharField(max_length=300)
html
<form action="" method="post">
<input type="text" name="title_input" id="title_input">
<label for="title_input">Title</label>
<input type="file" name="media_input" id="media_input">
<label for="media_input">Media</label>
<input type="text" name="caption_input" id="caption_input">
<label for="caption_input">Caption</label>
<input type="submit" value="POST!">
</form>
Just ad the else block, like here:
if form.is_valid():
...
else:
print(form.errors)
It will output the <li></li> tag with the name of the field and the error.
You also forgot to add:
{% csrf_token %}
Inside of your <form></form> tag in the .html
Also the name attributes of <input> tags must be similar with the names of the fields in the model.
This always works for me.
Remove the "_input" from the "name" tag in HTML. The form is not able to find the field values. The name tag should have the same value as the corresponding attribute of the Form class.
I have a Django form with a check box for "Accept terms of service" but if I check it or not my app blocks the request with the message "you have to accept our Terms of service".
Here is my code:
forms.py
class ProfileModelForm(ModelForm):
class Meta:
model = UserProfile
fields = ['u_fullname',
'u_job',
'u_country',
'u_email',
'u_terms',
]
def clean(self):
cleaned_data = super(ProfileModelForm, self).clean()
u_fullname = cleaned_data.get('u_fullname')
u_job = cleaned_data.get('u_job')
u_country = cleaned_data.get('u_country')
u_email = cleaned_data.get('u_email')
u_terms = cleaned_data.get('u_terms')
if not u_terms:
raise forms.ValidationError("Please read and accept our Terms of Service")
if not u_fullname and not u_job and not u_country and not u_terms:
raise forms.ValidationError('You have to write something!')
return cleaned_data
Field u_terms is a Booleanfield in my model.
the views.py:
if request.method == 'POST':
if 'user_reg' in request.POST:
form = ProfileModelForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
#Create user and get the id
n_user = User.objects.create_user(username=request.POST['u_email'],
email=request.POST['u_email'],
password=request.POST['u_password'])
instance.user = User.objects.get(id=n_user.id)
instance.u_profile = 'U'
print("TERMS-->",request.POST['u_terms'])
instance.save()
return # Put return here
else:
messages.error(request, "Error")
#form = ProfileModelForm()
return render(request, 'login.html', {'form': form})
elif 'register' in request.POST:
pass
elif 'company' in request.POST:
pass
and the html template part related to my checkbox:
<div class="col-lg-12 no-pdd">
<div class="checky-sec st2">
<div class="fgt-sec">
<input type="checkbox" name="cc" id="c2" value={{ form.u_terms }}>
<label for="c2">
<span></span>
</label>
<small>Yes, I understand and agree to the workwise Terms & Conditions.</small>
</div><!--fgt-sec end-->
</div>
</div>
I imagine the problem is in my html part but I don't know how can I manage boolean fields from checkbox.
Someone can help me?
The "name" attribute of your <input> element does not match the POST attribute expected by your form: cc != u_terms.
You can solve this in two ways:
Use {{ form.u_terms }} to render the entire <input> tag. Note that you put that into the value attribute, which is wrong (look at the source code inside your browser, you'll see what I mean).
{{ form.u_terms }}
{{ form.u_terms.label_tag }}
If you must customise attributes of your <input> (which doesn't seem to be the case here), then make sure you still refer to your form's field so that the various attributes are correct:
<input type="checkbox" name="{{ form.u_terms.html_name }}" id="{{ form.u_terms.id_for_label }}" class="some-custom-class">
<label for="{{ form.u_terms.id_for_label }}"><span></span></label>
I want to update database values by HTML Forms
HTML form :
<form action="/school_manager/students/{{student.id}}/update/" method="post" accept-charset="utf-8">
{% csrf_token %}
<label for="update_name">Edit Name :</label><br/>
<input type="text" name="update_name" id="update_name" placeholder="Enter A Name" />
<input type="submit" value="Update"/>
</form>
views.py :
def update_student_detail(request, student_id):
list = get_object_or_404 ( student, pk=student_id)
if request.method == 'POST' :
student.First_Name = request.POST.get('update_name','')
list.save()
return HttpResponseRedirect('/school_manager/students/' + student_id)
When I run the program and type a word in text box, after submit it does not work. I can't see any change to my database.
I found my fault
in views.py calling student for change database values is wrong
When we created a list of database tuple, values can edit by using that list
def update_student_detail(request, student_id):
list = get_object_or_404 ( student, pk=student_id)
if request.method == 'POST' :
list.First_Name = request.POST.get('update_name','')
list.save()
return HttpResponseRedirect('/school_manager/students/' + student_id)
i have an custom form , whenever i fetch the form values to save in the database than it display an error ( applicationform() got an unexpected keyword argument 'job_title' ) and the values are not save in the table.
views.py :-
def applicationvalue(request):
if request.method == 'POST':
getjobtitle = request.POST['jobtitle']
getintable = applicationform(job_title=getjobtitle)
getintable.save()
print getjobtitle
return HttpResponse(getintable)
else:
return render_to_response('registration/applicationform.html')
my form is :-
<form method="POST" action="#" class="form-horizontal" id="applicationform" name="appform">
<input type="text" id="u_jobtitle" class="input-xlarge" name="jobtitle" value=" " />
<button class="btn btn-gebo" type="submit" name="usubmit">Save changes</button>
whenever i fetch the values from form to save the values in table field " job_title " than it will display an error :-
applicationform() got an unexpected keyword argument 'job_title'
Change input field name to job_title in your html
<input name="job_title" type="text" id="u_jobtitle" class="input-xlarge" value=" " />
-------------^ changed
and then in view do
def applicationvalue(request):
if request.method == 'POST':
#Dont need this
#getjobtitle = request.POST['jobtitle']
#---------------------------Use request.POST
getintable = applicationform(request.POST)
getintable.save()
print getjobtitle
return HttpResponse(getintable)
else:
return render_to_response('registration/applicationform.html')
It will be better if you use same form to render html instead of hand coding it.
The applicationform constructor should take the request.POST as argument.
But it seems to me that you are not using django forms in the "right" way. I think that your view doesn't follow the django philosophy for using form.
In your case, you should have a model:
from django.db import models
class Application(models.Model):
job_title = models.CharField(max_length=100)
Based on this model, you can declare a ModelForm:
from django import forms
from .models import ApplicationModel
class ApplicationForm(forms.ModelForm):
class Meta:
model = ApplicationModel
fields = ('job_title',)
Then you can use this form in your view
def applicationvalue(request):
if request.method == 'POST':
form = ApplicationForm(request.POST)
if form.is_valid():
#This is called when the form fields are ok and we can create the object
application_object = form.save()
return HttpResponse("Some HTML code") # or HttResponseRedirect("/any_url")
else:
form = ApplicationForm()
#This called when we need to display the form: get or error in form fields
return render_to_response('registration/applicationform.html', {'form': form})
finally you should have a registration/applicationform.html template with something like:
{% extends "base.html" %}
{% block content %}
<form action="" method="post">{% csrf_token %}
<table>
{{form.as_table}}
</table>
<input type="submit" value="Add">
</form>
{% endblock %}
I hope it helps
I used this code previously it worked fine and i was suggested to use ModelForm by another member, it did make sense to use the form.is_valid() function etc.. so thought of giving it a try.
I went through some other examples on the internet but mine does not seem to work for some reason, or may be I am not doing it right, I get the following when I print the form in the view, and it goes to the else statement, so my form does not get saved
<input id="id_product" type="text" name="product" value="aassddf" maxlength="250" />
FAIL
My model.py
from django.db import models
from django.forms import ModelForm
class Category(models.Model):
name = models.CharField(max_length=250)
def __unicode__(self):
return self.name
class Product(models.Model):
category = models.ForeignKey(Category)
product = models.CharField(max_length=250)
quantity = models.IntegerField(default=0)
price = models.FloatField(default=0.0)
def __unicode__(self):
return self.product
class ProductForm(ModelForm):
class Meta:
model = Product
My views.py
from models import *
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
def index(request):
...
...
def add_product(request):
if request.method == 'POST':
form = ProductForm(request.POST)
print form['product']
if form.is_valid():
form.save()
return HttpResponseRedirect('/product')
else:
print 'FAIL'
return HttpResponseRedirect('/product')
My html
<form method="post" action="add_product/">
{% csrf_token %}
<label for="category">Category</label>
<select name="category" id="category">
{% for category in category_list %}
<option> {{ category.name }} </option>
{% endfor %}
</select>
<label for="product">Product</label>
<input type="text" name="product" id="product">
<label for="quantity">Quantitiy</label>
<input type="text" name="quantity" id="quantity">
<label for="price">Price</label>
<input type="text" name="price" id="price">
<input type="submit" value="Add New product" id="create">
</form>
Is there a better way i could save the data, using ModelForms ??
Thanks in advance for the help.
You should read the documentation. If the form is not valid, it will have a whole set of errors associated with it, which will tell you exactly why. But you just throw that away, and redirect to /product. The docs show exactly how to redisplay the form with the errors.
Also you should not write HTML form field tags directly in your template: use the form object from the view - {{ form.product }}, etc - as these will be repopulated with the appropriate values on redisplay.
Thanks to Daniel Roseman and Anuj Gupta I think I finally re-worked on my code on got it working in a standard way so it will generate the html form and validate errors.
So for anyone else who is trying to work django forms here is the code I worked on.
My model.py is was almost the same one i posted on the question but i removed
class ProductForm(ModelForm):
class Meta:
model = Product
I created a new form.py here is the code-
from django import forms
from models import Category
class ProductForm(forms.Form):
# Put all my Categories into a select option
category = forms.ModelChoiceField(queryset=Category.objects.all())
product = forms.CharField()
quantity = forms.IntegerField()
price = forms.FloatField()
My views.py changed had a lot of changes -
def add_product(request):
success = False
if request.method == "POST":
product_form = ProductForm(request.POST)
if product_form.is_valid():
success = True
category = Category.objects.get(name=product_form.cleaned_data['category'])
product = product_form.cleaned_data['product']
quantity = product_form.cleaned_data['quantity']
price = product_form.cleaned_data['price']
new_product = Product(category = category, product = product, quantity = quantity, price = price )
new_product.save()
new_product_form = ProductForm()
ctx2 = {'success':success, 'product_form':new_product_form}
return render_to_response('product/add_product.html', ctx2 , context_instance=RequestContext(request))
else:
product_form = ProductForm()
ctx = {'product_form':product_form}
return render_to_response('product/add_product.html', ctx , context_instance=RequestContext(request))
Finally in my html page i used {{ product_form.as_p }} so it created the forms dynamically
{% if success %}
<h3> product added successfully </h3>
{% endif %}
<form method="post" action=".">
{% csrf_token %}
{{ product_form.as_p }}
<input type="submit" value="Add New product" id="create">
<input type="reset" value="reset" id="reset">
</form>
This may not be the perfect solution, but for a starter like me this sounds good, and at times you just get lost while reading the docs lol, hope it helps some one.
Cheers
Try:
<form method="post" action="add_product/">
{% csrf_token %}
{{ form.as_p }}
</form>
in your template, instead of hand-coding the form's input tags. This shortcut will generate the form html for you, as well as print validation errors.
Make sure you return the form object to the template when:
There is no request.POST (form has not been submitted)
form.is_valid() fails (form has validation errors)
Of course, this is only to get you started. You really should read the docs