I'm learning Django and have some troubles with forms. I try to create a simple form where I type a name and show it on another page. But is_valid() always returns false. Please, help me to find my error
forms.py
from django import forms
class OrderForm(forms.Form):
user=forms.CharField(max_length=100)
views.py
def order(request):
return render(request, 'myapp/order.html', {})
def contact(request):
username='not logged'
if request.method == 'POST' :
form=OrderForm(request.POST)
if form.is_valid():
username=form.cleaned_data['username']
else:
username='not worked'
else:
form=OrderForm()
return render(request, 'myapp/contacts.html', {'username':username})
order.html
<form name = "form" action = "{% url 'contact' %}" method = "POST" >
{% csrf_token %}
<input type="text" name="username" placeholder="Name">
<button type="submit">Login</button>
</form>
contacts.html
You are : <strong>{{ username }}</strong>
Your form control has the name username in HTML, while your form's field is named user in Django. Thus, nothing is set in the form field.
Normally you'd put the form into the context and then render it either as {{ form }} or the like, or render each field, rather than build your own form controls. The docs show how: https://docs.djangoproject.com/en/1.10/topics/forms/#working-with-form-templates
views.py
from forms import OrderForm
def order(request):
form = OrderForm()
return render(request, 'myapp/order.html', {"form" : form})
order.html
<form name = "form" action = "{% url 'contact' %}" method = "POST" >
{% csrf_token %}
{{form.as_p}}
<button type="submit">Login</button>
</form>
At the time of rendering template {{form.as_p}} looks like
<p><label for="id_username">Username:</label>
<input id="id_username" type="text" name="username" maxlength="100" required /></p>
Related
I want to create a form in my navigation bar. I am using a context processor for that.
I created themeChoice field in my UserProfile model. What I want to is when user click submit button, form will be save. I tried something but it did not work, my view prints nothing. How can I do that?
Note: my context processor is working.
views.py
def approval_context_processor(request):
...
if request.method == 'POST':
form_theme = UserThemeChoiceform(request.POST)
if form_theme.is_valid():
user_who = request.POST.get('user_who', None)
user = UserProfile.objects.get(id=user_who)
print(user_who)
form_theme.save()
return redirect('home')
context= {
...
'form': form_theme,
}
return context
navigation.html
<form method="POST" id="theme" action="#">
{% csrf_token %}
<input type="hidden" name="user_who" value="{{ request.user }}" >
<button type="submit" class="btn btn-success">Send</button>
</form>
I have created a form with select field in template ehrinfo.html
<form action="{% url 'ehrs:compcreate' %}" method="GET">
<select>
<option value="Vital Signs">Vital Signs</option>
<option value="Cancer Signs">Cancer Signs</option>
</select><br><br>
<input type="submit" value="Select Template" class="addehr">
</form>
I have defined form class as:
class templateselect(forms.Form):
CHOICES = (
('Vital Signs', 'Vital Signs'),
('Cancer Signs', 'Cancer Signs'),
)
template = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
Now I want to get selected text from this form in view compcreate. So I used:
def compcreate(request):
if request.method == 'GET':
form = templateselect(request.GET)
print("a")
if form.is_valid():
print("b")
template = str(form.cleaned_data["template"])
but it cant get past the if form.is_valid(): part as 'a' is printed but 'b' is not printed on console. What is the problem? How can I get the selected text in compcreate()?
The proper way to render your form would be to pass it in to your template via the context object and change your template. For example:
<form action="{% url 'ehrs:compcreate' %}" method="GET">
{{ form.as_p }}<br><br>
<input type="submit" value="Select Template" class="addehr">
</form>
If you want to stick with your current setup, looking at the html produced by the previous solution suggests that adding a name (equal to the name of your field in the Form class declaration) to your select field should also work:
<form action="{% url 'ehrs:compcreate' %}" method="GET">
<select name="template">
<option value="Vital Signs">Vital Signs</option>
<option value="Cancer Signs">Cancer Signs</option>
</select><br><br>
<input type="submit" value="Select Template" class="addehr">
This approach works with ModelForm and POST request:
def compcreate(request):
if request.method == 'POST':
form = templateselect(request.POST)
if form.is_valid():
ts = form.save(commit=False)
print(ts.template)
Let me know if it works in your case.
I have created models.py, forms.py, views.py & registeration.html.
At the moment in registeration.html I am directly importing the django form like {{reg_form.as_p}}, I can also do it in following two ways: {{ form.as_table }} or {{ form.as_ul }}. what I want is to have a real control over the fields to be displayed. Meaning to say some fields may be tabular, some may be list etc with specific css.
What I tried in html to access the field is mentioned below:
id={{form.id_FullName}} name={{form.FullName}}
In models.py I have:
FullName = models.CharField(max_length = 100)
The above way didnt work, I want some way to access the django fields in HTML.
Add name and pass the modelname ,
Change like this,
<input type="text" id="id_FullName" value="" name="FullName" />.
and submit your form.
Example , lets say signup form :
forms.py,
class SignUpForm(forms.ModelForm):
email = forms.CharField(label='email', max_length=100)
password = forms.CharField(label='password', max_length=100)
def __init__(self, *args, **kargs):
super(SignUpForm, self).__init__(*args, **kargs)
class Meta:
model = User
fields = '__all__'
views.py,
def signup(request):
form = SignUpForm(request.POST or None)
if request.method == 'POST':
form = SignUpForm(request.POST or None)
if not form.is_valid():
print form.errors
return render(request, 'signup.html', {'form': form})
else:
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
new_user = User.objects.create_user(email=email,
password=password,
)
new_user.is_active = True
new_user.save()
return redirect('login')
else:
return render(request, 'signup.html', {'form': form})
urls.py
url(r'^signup', views.signup, name='signup'),
Finally in your templates ie signup.html,
<form action="." method="post"> {% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name="email" id="inputUsernameEmail" placeholder="Email">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" id="inputPassword" placeholder="Password">
</div>
<input type="submit" name="Sign up" value="Sign up" id="Sign_up" class="button_drop outline">
</form>
You can render the field manually.[Documentation]
Here is a sample taken from the docs for a subject field
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
I have in my template:
This is passed by {{form}}
<form action="" method="POST">
Inicio: <input type="text" id="start">
<input type="submit" value="Sned" >
{% csrf_token %}
</form>
Then in the views.py
def test(request):
if request.method != 'POST':
context = {'form': 'by GET'}
return render(request, 'test.html', context)
else:
if 'start' in request.POST:
start = request.POST['start']
else:
start = False
context = {'form': start}
return render(request, 'test.html', context)
It seems that always return False
If I dont check the existance of the key I have this error:
MultiValueDictKeyError
And the erropage says : "'start'" (single plus double quotes)
id is intended for javascript and css purposes. For variables that are important on server side, you should use name tag.
<input type="text" id="start" name="start">
You need to add a name attribute in your input, so when you are getting the POST data it will be found.
<form action="" method="POST">
Inicio: <input type="text" id="start" name="start">
<input type="submit" value="Sned" >
{% csrf_token %}
</form>
Also I recommend you to do the following change in your view:
Replace
request.POST['start']
by:
request.POST.get('start')
So, if the field is not found, it will be reassigned whith a None value.
add name
<input type="text" name="start" id="start">
When I wanted use my registration form in my site, I get ERROR 403: "CSRF verification failed. Request aborted." In source of this website I realised that is missing. This is part of view-source from my site:
<div style="margin-left:35%;margin-right:35%;">
<fieldset>
<legend> Wszystkie pola oprócz numeru telefonu należy wypełnić </legend>
<form method="post" action=".">
<p><label for="id_username">Login:</label> <input id="id_username" maxlength="30" name="username" type="text" required/></p>
<p><label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required /></p>
<p><label for="id_password1">Hasło:</label> <input id="id_password1" name="password1" type="password" required /></p>
<p><label for="id_password2">Powtórz hasło:</label> <input id="id_password2" name="password2" type="password" required /></p>
<p><label for="id_phone">Telefon:</label> <input id="id_phone" maxlength="20" name="phone" type="text" /></p>
<p><label for="id_log_on">Logowanie po rejestracji:</label><input id="id_log_on" name="log_on" type="checkbox" /></p>
<input type="submit" value="Rejestracja"><input type="reset" value="Wartości początkowe">
</form>
</fieldset>
</div>
I was surprised of that, because in my files on Pythonanythere this fragment of code is present.
This is part of my file register.html on Pythonanythere:
<div style="margin-left:35%;margin-right:35%;">
<fieldset>
<legend> Wszystkie pola oprócz numeru telefonu należy wypełnić </legend>
<form method="post" action=".">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Rejestracja"><input type="reset" value="Wartości początkowe">
</form>
</fieldset>
</div>
What am I doing wrong that my webpage don't see this piece of code? It is seamed on server but on webpage view-source It isn't.
EDIT:
This is view, which render my template:
def register(request):
if request.method == 'POST':
form = FormularzRejestracji(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
user.last_name = form.cleaned_data['phone']
user.save()
if form.cleaned_data['log_on']:
user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
login(request, user)
template = get_template("osnowa_app/point_list.html")
variables = RequestContext(request, {'user': user})
output = template.render(variables)
return HttpResponseRedirect("/")
else:
template = get_template("osnowa_app/register_success.html")
variables = RequestContext(request, {'username': form.cleaned_data['username']})
output = template.render(variables)
return HttpResponse(output)
else:
form = FormularzRejestracji()
template = get_template("osnowa_app/register.html")
form = FormularzRejestracji()
variables = RequestContext(request, {'form': form})
output = template.render(variables)
return HttpResponse(output)
You should pass a plain dict and the request object to template.render(), not a RequestContext. The template engine will convert it to a RequestContext for you:
template = get_template("osnowa_app/register.html")
context = {'form': form}
output = template.render(context, request)
Right now, the template.render() function sees a dict-like object as the first argument, but no request as the second argument. Without a request as the second argument, it converts the dict-like RequestContext into a plain Context object. Since the Context object doesn't run context processors, your context is missing the csrf token.
Alternatively you can just use the render shortcut, which returns a HttpResponse object with the rendered template as content:
from django.shortcuts import render
def register(request):
...
return render(request, "osnowa_app/register.html", {'form': form})
This particular case is also being discussed in ticket #27258.
CSRF token gets included in HTML form by calling hidden_tag function on your form object.
For example check this gist, line number 6. This is how you add form and it's elements in jinja.