Django CSRF verification failed on post method - django

I dont understand this one...
the token is in the template and the 'django.middleware.csrf.CsrfViewMiddleware' is define in MIDDLEWARE_CLASSES
views.py:
from django.shortcuts import render_to_response
from ezmapping.models import *
from django.forms.models import modelformset_factory
def setMapOptions(request):
ezMapFormSet = modelformset_factory(ezMap, fields=('map_name', 'zoom_level', 'center_lat', 'center_long', 'map_width', 'map_height'))
if request.method == 'POST':
formset = ezMapFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
else:
formset = ezMapFormSet(queryset=ezMap.objects.filter(map_name ='first test'))
return render_to_response("ezmapping/manage_mapOptions.html", {'formset': formset,})
template:
<html>
<head>
<title>Manage Map Options</title>
</head>
<body>
<h1>Define map options</h1>
<form method="post" action="">{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
<input type="submit" value="Submit" />
</form>
</body>
</html>

You need to use RequestContext to use the CSRF tags.
https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext
context = RequestContext(request, {
'foo': 'bar',
})
# or
render_to_response('foo.html', {}, context_instance=RequestContext(request))
RequestContext takes the request object and loads all kinds of variables automatically, including CSRF.

Related

Why don't my entries get saved in the database in Django?

The post requests from the frontend do not get saved in the database, without any error shown. However, when I manually add entries from the admin panel, it shows on the frontend.
My index.html(form part):
<form class="main__input--form" method="POST">
{% csrf_token %}
<p class="main__input--text">
<textarea name="content" id="content" class="main__input--content" cols="35" rows="8" aria-label="Entry content" placeholder="Enter text here..."></textarea>
</p>
<button class="main__input--submit" type="submit">Vent</button>
</form>
My extension of index which loops through the database entries:
{% for obj in all_vents %}
<div>
<h1>{{obj.vent}}</h1>
</div>
<br />
{% endfor %}
My models.py:
class Vents(models.Model):
vent = models.CharField(max_length=10000)
def __str__(self):
return self.vent
My forms.py:
from django import forms
from .models import Vents
class VentForm(forms.ModelForm):
class Meta:
model = Vents
fields = ['vent']
My views.py:
from django.shortcuts import render, redirect
from .forms import VentForm
from .models import Vents
def ventout(request):
if request.method == "POST":
form = VentForm(request.POST or None)
if form.is_valid():
form.save()
return redirect("ventout")
else:
all_vents = Vents.objects.all()
return render(request, "ventout.html", {"all_vents": all_vents})
Views:
def ventout(request):
all_vents = Vents.objects.all()
if request.method == "POST":
form = VentForm(request.POST or None)
if form.is_valid():
form.save()
return redirect("ventout")
else:
form = VentForm()
context = {"all_vents": all_vents, "form":form}
return render(request, "ventout.html", context)
Template:
<form class="main__input--form" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="main__input--submit">Vent</button>
</form>
you could install/use "crispy_forms_tags" to make the form look better,
https://django-crispy-forms.readthedocs.io/en/latest/index.html
if you want to go further you could install/use "widget_tweaks"
https://pypi.org/project/django-widget-tweaks/
Your index.html from part should have {{ form }} form tag, as I guess.
Try Using following code
<form class="main__input--form" method="POST">
{% csrf_token %}
{{ form }}
<p class="main__input--text">
<textarea name="content" id="content" class="main__input--content"
cols="35" rows="8" aria-label="Entry content" placeholder="Enter text here...">
</textarea>
</p>
<button class="main__input--submit" type="submit" value="Submit">Vent</button>
</form>

Django - formset with crispy forms - missing management form data

I'm trying to render this form set:
ProductFormSet = modelformset_factory(
model=Product,
fields='__all__',
extra=5,
)
class ProductFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_tag = False
self.layout = Layout(
Row(
'productCategory',
'name',
'measurement_unit',
)
)
self.render_required_fields = True
with this view:
def product_create(request):
helper = ProductFormSetHelper()
context = {
'helper': helper,
'title': 'Nuovi Prodotti',
}
if request.method == 'GET':
formset = ProductFormSet(queryset=Product.objects.none())
context['formset'] = formset
elif request.method == 'POST':
formset = ProductFormSet(request.POST)
context['formset'] = formset
if formset.is_valid():
formset.save()
messages.success(request, 'Prodotti aggiunti correttamente', fail_silently=True)
return HttpResponseRedirect(reverse('warehouse:products_list'))
else:
return render(request, 'warehouse/product_create.html', context)
return render(request, 'warehouse/product_create.html', context)
and this template:
{% extends "masterpage.html" %}
{% load static %}
{% block headTitle %}
<title>Nuovo Prodotto</title>
{% endblock %}
{% block contentHead %}
{% endblock %}
{% block contentBody %}
{% load document_tags %}
{% load custom_tags %}
{% load crispy_forms_tags %}
<FORM method="POST" autocomplete="off">
<div class="alert alert-info">
{{ title }}
</div>
{{ formset.management_form }}
{% crispy formset helper %}
<input type="submit" class="btn btn-primary margin-left" value="SALVA">
</FORM>
{% endblock %}
Problem is that when I submit the form I get the: ValidationError: management form data are missing! First of all, using crispy forms the management data should be included, second even if I explicitly call with the tag, I still get the ValidationError.
in Every forum I searched online, everyone was missing the management form tag, so I have no clue on what could be wrong....
Any idea?
thank you very much
C
in your Post method you didnt include the "queryset"
formset = ProductFormSet(queryset=Product.objects.WHATEVER_YOU_CHOOSE, request.POST)
and for crispy forms
{% load crispy_forms_tags %}
<form method="post">
{% csrf_token %}
{{ formset|crispy }}
{{ formset.management_form }}
<input type="submit" class="btn btn-primary margin-left" value="SALVA">
</form>
and because you are not working in get_context_data fucntion, just keep it simple
context = {'formset':formset}
Exemple from the docs
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author
def manage_authors(request):
AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
if request.method == "POST":
formset = AuthorFormSet(
request.POST, request.FILES,
queryset=Author.objects.filter(name__startswith='O'),
)
if formset.is_valid():
formset.save()
# Do something.
else:
formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
return render(request, 'manage_authors.html', {'formset': formset})
Hope it can help others. Since I'm having troubles configuring the thousand separator, I tried to change the input.html widget in /templates/django/forms/widgets by adding the |intcomma filter.
This altered the management form data ( one field is set to 1000 by default ), thus corrupting the whole form.

Upload html in Django

Code in template:
<form action="/html/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" id="html_file" name="html_file" />
<input type="submit" value="Upload" />
</form>
and in view
def add_html(request):
if request.POST:
#do something with html
return redirect('/')
else:
return render_to_response('add_html.html')
I need to html-file is loaded and read its contents, not upload to the server.
But I get an error:
csrf token missing or incorrect
How fix?
My guess is that the {% csrf_token %} is empty when your template is rendered.
Per the CSRF documentation you should use the render function instead of the render_to_response function to ensure the RequestContext, which includes the csrf_token, is properly loaded into your template.
You can achieve what you want with the following code:
forms.py:
from django import forms
class ReadFileForm(forms.Form):
file = forms.FileField()
views.py:
from .forms import ReadFileForm
def read_file(request):
form = ReadFileForm()
if request.method == 'POST':
form = ReadFileForm(request.POST, request.FILES)
if form.is_valid():
content = request.FILES['file'].read()
# Do something with content
return render(request, 'read_file.html', locals())
templates/read_file.html:
<html>
<head></head>
<body>
<h3>Read File Content</h3>
<form enctype="multipart/form-data" action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Save">
</form>
</body>
</html>

No input fields in Django when making a form

I'm new to django and I'm trying to create forms, but whenever I run this I end up with a submit button with no input fields. If you see any other mistakes, don't hesitate to tell me.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import *
def form(request):
if request.method == 'POST':
form = forma(request.POST)
if form.is_valid():
return HttpResponseRedirect('index.html')
else:
form = forma()
return render(request, 'action.html', {"form":form})
def action(request):
return render(request, 'action.html')
**forms.py **
from django import forms
class forma(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
index.html
<body>
<section id = "sec">
<h1>... </h1>
<h3> ... </h3>
<h4> ... <h4>
<button> ... </button>
<p>{{hola}} alo {{darwich}}</p>
<form action= "action.html" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</section>
<body>

Django - Link on submit

I have a form with a POST Submit button. I want to link to a new page when the form is submitted and when the form.is_valid().
Is it better to make the link in the view or in the template? How to do it?
view.py:
from django.shortcuts import render_to_response
from ezmapping.models import *
from django.forms.models import modelformset_factory
def setName(request):
ezAppFormSet = modelformset_factory(ezApp, extra=1, fields=('name'))
formset = ezAppFormSet(queryset=ezApp.objects.none())
if request.method == 'POST':
formset = ezAppFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
return render_to_response("project/manage_new.html", {'formset': formset, 'title': "New"}, context_instance=RequestContext(request))
template.html
{% extends "basemap.html" %}
{% block content %}
<table border="1">
<tr>
<td>
<h1>Define new App options</h1>
{% if formset.errors %}
<p style="color: red;">
Please correct the error{{ formset.errors|pluralize }} below.
</p>
{% endif %}
<form method="post" action="." encrypt="multipart/form-data">{% csrf_token %}
{{ formset.as_p }}
<input type="submit" value="Submit">
</form>
</td>
</tr>
</table>
{% endblock %}
You can use HttpResponseRedirect() in the view like this:
from django.shortcuts import render_to_response
from ezmapping.models import *
from django.forms.models import modelformset_factory
def setName(request):
ezAppFormSet = modelformset_factory(ezApp, extra=1, fields=('name'))
formset = ezAppFormSet(queryset=ezApp.objects.none())
if request.method == 'POST':
formset = ezAppFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
next_link = u"/next/"
return HttpResponseRedirect(next_link)
return render_to_response("project/manage_new.html", {'formset': formset, 'title': "New"}, context_instance=RequestContext(request))
Sure. Just return a render_to_response inside of your conditional for request.method == 'POST', or optionally, just set up the context and template as variables to hand into render_to_response as such:
Paraphrased:
def foo(request):
template = 'template1.html'
# form and formsets here set into `context` as a dictionary
if request.method == 'POST':
template = 'template2.html'
return render_to_response(template, context)
[EDIT]
When I re-read your question, if you want to redirect to a different view if your form is valid, then return an HttpResponseRedirect instead.
If I understand your question correctly.
Your view:
from django.shortcuts import render_to_response
from ezmapping.models import *
from django.forms.models import modelformset_factory
def setName(request):
ezAppFormSet = modelformset_factory(ezApp, extra=1, fields=('name'))
formset = ezAppFormSet(queryset=ezApp.objects.none())
if request.method == 'POST':
formset = ezAppFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
submit_link = True # 2*
else:
submit_link = False
return render_to_response("project/manage_new.html", {'submit_link': submit_link, 'formset': formset, 'title': "New"}, context_instance=RequestContext(request))
Your template:
{% extends "basemap.html" %}
{% block content %}
<table border="1">
<tr>
<td>
<h1>Define new App options</h1>
{% if formset.errors %}
<p style="color: red;">
Please correct the error{{ formset.errors|pluralize }} below.
</p>
{% endif %}
<form method="post" action="." encrypt="multipart/form-data">{% csrf_token %}
{{ formset.as_p }}
<input type="submit" value="Submit">
</form>
{% if submit_link %}
<a href='/next/'>Data is saved, let's continue.</a>
{% endif %}
</td>
</tr>
</table>
{% endblock %}
Update.
And yes, if you want to redirect (not to show the next link) just place:
from django.shortcuts import redirect
...
return redirect( 'you-url' )
Instead of 2*.