CSRF token missing or incorrect [duplicate] - python

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
CSRF Protection in Django 1.4
I am trying to make a simple system for ticket reservation for rockets using Django. However, every time I try to reserve a ticket, I get the Forbidden 403 error: CSRF token missing or incorrect.
Here is my code:
models.py:
class Tickets(models.Model):
rocket_line = models.ForeignKey('Rockets')
date = models.DateField()
number_of_seats = models.IntegerField()
email = models.CharField(max_length=50)
ordered_on = models.DateTimeField()
total_price = models.DecimalField(max_digits=10, decimal_places=2)
def __unicode__(self):
return str(self.id)
views.py:
def order(request):
if request.method == 'POST':
order = Tickets(
rocket_line = Rockets.objects.get(id=request.POST['rocket_line']),
date=request.POST['date'],
number_of_seats=request.POST['number_of_seats'],
email=request.POST['email'],
ordered_on=datetime.now(),
total_price=(float(number_of_seats) * float(Rockets.objects.get(id=request.POST['rocket_line']).rprice))
)
order.save()
return HttpResponseRedirect('/menu/')
else:
all_rockets = Rockets.objects.all().order_by('rtime')
return render_to_response('order.html', { 'all_rockets': all_rockets}, RequestContext(request))
order.html:
<h1>You can order a ticket here:</h1>
<form action="/order/" method="post">
<p>
<label>Rocket_line</label>
<select name="rocket_line">
{% for rocket in all_rockets %}
<option value="{{ rocket.id }}">{{ rocket }}</option>
{% endfor %}
</select>
<label>Date</label>
<input name="date" value="YYYY-MM-DD" type="text" size="10" />
<label>Number of seats</label>
<input name="number_of_seats" value="" type="text" size="10" />
<label>E-mail</label>
<input name="email" value="#" type="text" size="50" />
<br /><br />
<input class="button" value="Order" type="submit" />
</p>
</form>
<br />
Could you help me to resolve, where the problem might be?

taken from the almighty django's docs:
Step 1:
Add the middleware 'django.middleware.csrf.CsrfViewMiddleware' to your list of middleware classes, MIDDLEWARE_CLASSES. (It should come before any view middleware that assume that CSRF attacks have been dealt with.)
Step 2:
<form action="." method="post">{% csrf_token %}
that {% csrf_token %} is all you need to add to your template.
there's other solutions around (decorators or ajax based) but this one is the fastest and most used (i think, at least... it requires no hassle whatsoever to be implemented)

Related

How to fix error "The view app.views.uploadform didn't return an HttpResponse object. It returned None instead."?

So I have a form in a html document and I'm trying to use it to add a new item to my django database.
Here is the HTML form :
<form method="POST" action="{% url 'uploadform' %}" enctype="multipart/form-data">
{% csrf_token %}
<label for="name">Name:</label><br>
<input type="text" id="name" name="name"><br>
<label for="details">Details:</label><br>
<input type="text" id="details" name="details"><br>
<label for="littype">Type of Literature:</label><br>
<input type="text" id="littype" name="littype"><br>
<label for="image">Cover:</label><br>
<input type="file" id="image" name="image"><br>
<input type="submit" value="Submit">
</form>
Here is my views.py handling the function :
def uploadform(request):
if request.method == 'POST':
if request.POST.get('name') and request.POST.get('details') and
request.POST.get('littype') and request.POST.get('image'):
post = PostForm()
post.name = request.POST.get('name')
post.details = request.POST.get('details')
post.littype = request.POST.get('littype')
post.image = request.POST.get('image')
if PostForm.is_valid():
PostForm.save()
return render(request, 'uploadform.html')
else:
return render(request, 'uploadform.html')
Here is my models.py even though i think the issue is in views.py :
class PostForm(models.Model):
name = models.CharField(max_length=200)
details = models.TextField()
littype = models.TextField()
image = models.FileField(upload_to='app/files/')
And finally for the issue, im getting an error saying "The view app.views.uploadform didn't return an HttpResponse object. It returned None instead.". I'm not sure what is causing the error and in addition,if there are any changes I have to make thats stopping the form from being turned into a new item in my database, I'd love to get help for that too.
Thanks for any answers! Have a good day!

Django model works on local but not after deploy

I am making a simple personal website. I make a box to input user data (name, email, and message). I want this data is sent to my django admin. I have test it and it works in local. But when i deploy it, i didn't get any data whenever i submit from the box. Note : i do not use django form for some reason. I want to use my own custom form.
this is my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Feedback
from .forms import FeedbackForm
def index(request):
if (request.method == "POST"):
name = request.POST.get("Name")
email = request.POST.get("Email")
message = request.POST.get("Message")
record = Feedback(name=name, email=email, message=message)
record.save()
return render(request, 'main.html')
this is my models.py
from django.db import models
class Feedback(models.Model) :
name = models.CharField(max_length=50)
email = models.EmailField()
message = models.CharField(max_length=200)
def __str__(self):
return self.name
this is my html form
<form action="{% url 'index' %}" method="POST" target="_self">
{% csrf_token %}
<div class="w3-row-padding" style="margin:0 -16px 8px -16px">
<div class="w3-half">
<input class="w3-input w3-border" type="text" placeholder="Name" required name="Name" >
</div>
<div class="w3-half">
<input class="w3-input w3-border" type="email" placeholder="Email" required name="Email">
</div>
</div>
<input class="w3-input w3-border" type="text" placeholder="Message" required name="Message" >
<button class="w3-button w3-black w3-right w3-section" type="submit">
<i class="fa fa-paper-plane"></i> SEND MESSAGE
</button>
</form>
I'm not sure what platform you have deployed the project on, but one of the first things I would try is to make sure you have run database migration. (Which I'm assuming you have done if you have access to the admin area, but it might be worth running again just to make sure.)
python manage.py makemigrations
python manage.py migrate
I made some modifications to your HTML form to more closely follow the Django documentation. Notably, the addition of enctype="multipart/form-data" and an id tag to each input: i.e. id="name". Here is a link to the documentation: https://docs.djangoproject.com/en/3.1/topics/forms/
<form action="{% url 'index' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="w3-row-padding" style="margin:0 -16px 8px -16px">
<div class="w3-half">
<input class="w3-input w3-border" type="text" placeholder="Name" name="Name" id="name" required>
</div>
<div class="w3-half">
<input class="w3-input w3-border" type="email" placeholder="Email" name="Email" id="email" required>
</div>
</div>
<input class="w3-input w3-border" type="text" placeholder="Message" name="Message" id="message" required>
<button class="w3-button w3-black w3-right w3-section" type="submit"><i class="fa fa-paper-plane"></i>SEND MESSAGE</button>
</form>
It could be an issue with copying/pasting code, but I noticed the fields on your model are over-indented. Make sure you are using a single tab before each field.
# models.py
class Feedback(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
message = models.CharField(max_length=200)
def __str__(self):
return self.name
If you are able to see the terminal, are you getting a 200 response with your POST request? It should look something like this:
"POST / HTTP/1.1" 200
One of the other things I'd check is to ensure your database is configured properly in settings.py (This is assuming you are using the sqlite database)
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
If you aren't seeing anything in the admin area, make sure you have registered your model in admin.py
from django.contrib import admin
from .models import Feedback
admin.site.register(Feedback)

Django check if checkbox is selected

I'm currently working on a fairly simple django project and could use some help. Its just a simple database query front end.
Currently I am stuck on refining the search using checkboxes, radio buttons etc
The issue I'm having is figuring out how to know when a checkbox (or multiple) is selected. My code so far is as such:
views.py
def search(request):
if 'q' in request.GET:
q = request.GET['q']
if not q:
error = True;
elif len(q) > 22:
error = True;
else:
sequence = Targets.objects.filter(gene__icontains=q)
request.session[key] = pickle.dumps(sequence.query)
return render(request, 'result.html', {'sequence' : sequence, 'query' : q, 'error' : False})
return render(request, 'search.html', {'error': True})
search.html
<p>This is a test site</p></center>
<hr>
<center>
{% if error == true %}
<p><font color="red">Please enter a valid search term</p>
{% endif %}
<form action="" method="get">
<input type="text" name="q">
<input type="submit" value="Search"><br>
</form>
<form action="" method="post">
<input type='radio' name='locationbox' id='l_box1'> Display Location
<input type='radio' name='displaybox' id='d_box2'> Display Direction
</form>
</center>
My current idea is that I check which checkboxes/radio buttons are selected and depending which are, the right data will be queried and displayed in a table.
So specifically:
How do I check if specific check-boxes are checked? and how do I pass this information onto views.py
Radio Buttons:
In the HTML for your radio buttons, you need all related radio inputs to share the same name, have a predefined "value" attribute, and optimally, have a surrounding label tag, like this:
<form action="" method="post">
<label for="l_box1"><input type="radio" name="display_type" value="locationbox" id="l_box1">Display Location</label>
<label for="d_box2"><input type="radio" name="display_type" value="displaybox" id="d_box2"> Display Direction</label>
</form>
Then in your view, you can look up which was selected by checking for the shared "name" attribute in the POST data. It's value will be the associated "value" attribute of the HTML input tag:
# views.py
def my_view(request):
...
if request.method == "POST":
display_type = request.POST.get("display_type", None)
if display_type in ["locationbox", "displaybox"]:
# Handle whichever was selected here
# But, this is not the best way to do it. See below...
That works, but it requires manual checks. It's better to create a Django form first. Then Django will do those checks for you:
forms.py:
from django import forms
DISPLAY_CHOICES = (
("locationbox", "Display Location"),
("displaybox", "Display Direction")
)
class MyForm(forms.Form):
display_type = forms.ChoiceField(widget=forms.RadioSelect, choices=DISPLAY_CHOICES)
your_template.html:
<form action="" method="post">
{# This will display the radio button HTML for you #}
{{ form.as_p }}
{# You'll need a submit button or similar here to actually send the form #}
</form>
views.py:
from .forms import MyForm
from django.shortcuts import render
def my_view(request):
...
form = MyForm(request.POST or None)
if request.method == "POST":
# Have Django validate the form for you
if form.is_valid():
# The "display_type" key is now guaranteed to exist and
# guaranteed to be "displaybox" or "locationbox"
display_type = request.POST["display_type"]
...
# This will display the blank form for a GET request
# or show the errors on a POSTed form that was invalid
return render(request, 'your_template.html', {'form': form})
Checkboxes:
Checkboxes work like this:
forms.py:
class MyForm(forms.Form):
# For BooleanFields, required=False means that Django's validation
# will accept a checked or unchecked value, while required=True
# will validate that the user MUST check the box.
something_truthy = forms.BooleanField(required=False)
views.py:
def my_view(request):
...
form = MyForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
...
if request.POST["something_truthy"]:
# Checkbox was checked
...
Further reading:
https://docs.djangoproject.com/en/1.8/ref/forms/fields/#choicefield
https://docs.djangoproject.com/en/1.8/ref/forms/widgets/#radioselect
https://docs.djangoproject.com/en/1.8/ref/forms/fields/#booleanfield
In models :
class Tag:
published = BooleanField()
(...)
In the template:
{% for tag in tags %}
<label class="checkbox">
<input type="checkbox" name="tag[]" value="" {% if tag.published %}checked{% endif %}>
</label>
{% endfor %}
Assuming you are sending the form as a POST, the values of the selected checkboxes are in request.POST.getlist('tag').
For example :
<input type="checkbox" name="tag[]" value="1" />
<input type="checkbox" name="tag[]" value="2" />
<input type="checkbox" name="tag[]" value="3" />
<input type="checkbox" name="tag[]" value="4" />
Say if 1,4 were checked,
check_values = request.POST.getlist('tag')
check_values will contain [1,4] (those values that were checked)
{% for tag in tags %}
<label class="checkbox">
<input type="checkbox" name="tag[]" value=""
{% if tag.published %}checked{% endif %}>
</label>
{% endfor %}
<input type="checkbox" name="tag[]" value="1" />
<input type="checkbox" name="tag[]" value="2" />
<input type="checkbox" name="tag[]" value="3" />
<input type="checkbox" name="tag[]" value="4" />

Django - Form validation, clean method for both hidden and visible fields

I am trying to validate fields, one visible filled by the user, and an other one: hidden for the user but filled by the template.
Here is my form:
class AForm(forms.Form):
xxxx = forms.CharField(max_length=30)
yyyy = forms.CharField(max_length=30,widget=forms.HiddenInput)
def clean(self):
xxxx=self.cleaned_data['xxxx']
yyyy=self.cleaned_data['yyyy'] ##ERROR
if function_check(xxxx,yyyy)==False:
raise forms.ValidationError("Try again!")
return xxxx
In my template I have:
<form method="post" action="">
{% csrf_token %}
{{form.xxxx}}
<input id="id_yyyy" name="yyyy" type="hidden" value='{{ code_generated_value }}' maxlength="30">
<input type="submit"/>
</form>
The only error I get is : 'yyyy' at the yyyy=self.cleaned_data['yyyy'] line.
I found this question: Hidden field in Django form not in cleaned_data
But it was not very helping.
EDIT 1: Generated HTML code
<p><input id="id_xxxx" maxlength="30" name="xxxx" type="text" /></p>
<input id="id_yyyy" maxlength="30" name="yyyy" type="hidden" value='97a8eee9477b73dda401b15369f8db00a0d6ab79.png'>
<input type="submit"/>
Always check generated HTML and POST data for request. You will see any fields missing & stuff. Also, use .get(field_name) method.
Check here for more. How to properly access cleaned_data from super, etc.

django poplulate html form

How to set the html form fields without using django-forms.
If you do not wish to use django.forms, but get data from a model and display it into a html form, you could do something like this:
views.py
from django.shortcuts import render_to_response, redirect
from myApp.models import MyModel
def editForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
return render_to_response('formUpdate.html',{ 'model' : model })
def updateForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
model.firstname = request.POST['firstname']
model.lastname = request.POST['lastname']
model.save()
return redirect('home', message='your name has been updated')
template - formUpdate.html
{% extends "base.html" %}
{% block content %}
<form action="/updateForm/{{ model.id }}/" method="post">
First name: <input type="text" name="firstname" value="{{ model.firstname }}" /><br />
Last name: <input type="text" name="lastname" value="{{ model.lastname }}" /><br />
<input type="submit" value="submit" />
</form>
{% end block %}
models.py
from django.db import models
class MyModel(models.Model):
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'views.home', name="home"),
(r'^editForm/(?P<model_pk>\d+)/$', 'views.editForm'),
(r'^updateForm/(?P<model_pk>\d+)/$', 'views.updateForm'),
)
This is very similar to how forms are processed in PHP or similar, the model is passed into the template where the existing values are rendered. The id or pk (primary key) of the model is passed to the view via the URL and then updated values then returned to the storing view in the POST data where they can be retrieved and the updated values stored in the database.
One of the beauties of Django is how it balances speed of development with plugability - pretty much any of it's parts can be replaced or altered.
Having said this, is there a reason why you don't want to use django.forms? To my understanding a form simply performs most of the hard work in the example above for you, this is what django.forms are for. They also have other features, to help prevent malicious access of your web app, for example, OOTB. It is fairly easy to create ajax helper methods to retrieve and update them also.
You can do that as you would create a normal form in html. Just be careful to place the {% csrf_token %}. And the name of the input in the form, as they will be used in the view.
Eg:
<form method="post" action="#the url for the view">
{% csrf_token %}
...
...
<!-- fields that you want Eg: -->
<label for="username">User name:</label>
<input type="text" name="username" id="username" />
...
...
<input type="submit" value="Submit" />
</form>
Hope this helped.

Categories

Resources