I've encountered this issue but unfortunately still do not know how to fix it. The form renders perfectly, I enter the info and get a CSRF error. The reason given is token missing or incorrect.
View:
def eventSell(request, id):
c = {}
c.update(csrf(request))
event = SquidEvent.objects.get(pk = id)
listing_form = ListingForm(request.POST)
if request.user.is_authenticated():
if request.method == 'POST':
listing_form = ListingForm(request.POST)
if listing_form.is_valid():
cd = listing_form.cleaned_data
user = request.user
item = Object(price = cd['price'], seller = user)
item.save()
return HttpResponseRedirect(reverse('tixeng:index'), c)
#print listing_form
else:
return render_to_response('tixeng/list.html', {'event' : event, 'form' : listing_form}, c)
else:
return HttpResponseRedirect(reverse('allauth.account.views.login'))
Here is my template:
<form action="{% url 'app:eventSell' event.id %}" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
I think I've done everything right, I'm not sure what's causing the CSRF error. Also, in case its relevant I was following along with this as a guide:
http://www.djangobook.com/en/2.0/chapter07.html
This stack here Django "The view didn't return an HttpResponse object." was able to help me sort it out. Once I added context_instance = RequestContext(request) to my render_to_response it worked.
context_instance is deprecated since version 1.8.
You can use:
return render(request, 'admin/match_main.html', RequestContext(request, locals()))
Related
When I try to use a form to edit an object that includes an image upload I get "This field is required". A similar form works fine to create the object, but when I retrieve the object and attempt to modify other fields, it fails on the image.
#-------models.py:
class Star(models.Model):
firstname = models.CharField(max_length=32)
lastname = models.CharField(max_length=32, blank=True)
portrait = models.ImageField(upload_to='images/')
#------views.py:
class StarForm(forms.ModelForm):
class Meta:
model = Star
fields = ["firstname", "lastname", "portrait"]
def staredit(request, star_id):
instance = Star.objects.get(pk=star_id)
form = StarForm(request.POST or None, instance=instance)
context = {
"form": form,
}
return render(request, "stars/edit.html", context)
def starchange(request):
form = StarForm(request.POST, request.FILES)
if form.is_valid():
newstar.save()
context = {
"message": "The form was posted",
}
return render(request, "stars/edit.html", context)
else:
context = {
"message": form.errors,
}
return render(request, "stars/edit.html", context)
#-----edit.html
<form action="/starchange" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{{message}}
Error message:
portrait
This field is required.
You are not updating the instance, since you never have passed the instance to the view that should update it. When you make a POST requrest, the browser only submits the content of the form elements. There is no data about what has rendered the previous form, that data is lost.
You should specify the instance to update, so:
from django.shortcuts import get_object_or_404
def starchange(request, pk):
obj = get_object_or_404(Star, pk=pk)
form = StarForm(request.POST, request.FILES, instance=obj)
if form.is_valid():
form.save()
context = {
"message": "The form was posted",
}
return render(request, "stars/edit.html", context)
else:
context = {
"message": form.errors,
}
return render(request, "stars/edit.html", context)
in the urls, you thus should specify the primary key of the object to update:
urlpatterns = [
# …,
path('starchange/<int:pk>/', views.starchange, name='starchange')
]
and in the template, you should make a POST request to a view with the given instance:
<form action="{% url 'starchange' pk=form.instance.pk %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
This is one of the main reasons why often the same view is used both for a GET and POST request, since it makes it removes a lot of duplicate logic. Furthermore it is also more clean: you can use GET to retrieve the page, and POST to submit the page.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
I need a call a form on an HTML template where the user posts data which saves to model
The code is running without any errors
But the html page display only title and button
No text input fields
I have a form which is to be displayed on a html page so the user can input data and it saves the data into the model.I am not getting any errors while executing th code but the template does not display the form it just shows the title and submit button
def boqmodel1(request):
form = boqform(request.POST)
if form.is_valid():
obj=form.save(commit=False)
obj.save()
context = {'form': form}
return render(request, 'create.html', context)
else:
context = {'error': 'The post has been successfully created.
Please enter boq'}
return render(request, 'create.html', context)
MyTemplate
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create boq"/>
</form>
MY Url
urlpatterns = [
url(r'^create/', views.boqmodel1, name='boqmodel1'),
path('', views.boq, name='boq'),
]
First of all, your first request, without submitting form is GET. When you submit a form you send POST.
The form is not displaying, because your form is not valid in the first place. Your function should look like this:
def boqmodel1(request):
context = {}
if request.method == "GET":
form = boqform()
context["form"] = form
# if you post a form do all the saving
if request.method == "POST":
form = boqform(request.POST)
context = {'form': form}
if form.is_valid():
obj=form.save()
return render(request, 'create.html', context)
else:
context["errors"] = form.errors
return render(request, 'create.html', context)
If method is GET init your form and pass it to your context, so you can display it on frontend.
If method is POST, init your form with your data from frontend (request.POST), check if the form is valid. If it is valid - save it. If it is not valid, return your errors and display them as you wish.
I have a model in django that is as below:
class Student(Model):
nationality = CharField(max_length=200)
I have a form as below:
class StudentForm(ModelForm):
class Meta:
model = Student
fields = ('nationality', )
my template is as below:
<form method="GET" novalidate id="my_form">
{{ student_form.as_p }}
</form>
<button type="submit" form="my_form" name="my_form">Submit</button>
I have a view as below:
def home(request):
if request.POST:
return HttpResponse('This should never happen')
else:
if request.GET.get('nationality'):
student_form = StudentForm(request.GET)
if student_form.is_valid():
return HttpResponse('get from form submission')
else:
student_form = StudentForm()
print('get from client request')
return render(request, my_template, {'student_form': student_form})
The problem with this method is that if sb submits the form without filling the nationality field, the result would be 'get from client request' that is wrong because the validation error should happen because the request is from submitting a form not direct client get request.
What I can do is that I add a hidden field to my form as below:
<form method="GET" novalidate id="my_form">
{{ student_form.as_p }}
<input type="hidden" id="hidden" name="hidden" value="hidden">
</form>
<button type="submit" form="my_form" name="my_form">Submit</button>
and change my view as below:
def home(request):
if request.POST:
return HttpResponse('This should never happen')
else:
if request.GET.get('hidden'):
student_form = StudentForm(request.GET)
if student_form.is_valid():
return HttpResponse('get from form submission')
else:
student_form = StudentForm()
print('get from client request')
return render(request, my_template, {'student_form': student_form})
However, there should be another method to do this. There should be something in HTTP to tell us the request is fresh get request from client or it is from form submission. I am looking for this.
request.GET is a dictionary. request.GET.get('nationality') is falsy if the dictionary doesn't have the key 'nationality' but also if its value is the empty string (?nationality=). So you should just check the presence of the key, that way you know the form was submitted:
if 'nationality' in request.GET:
# initialise form with `request.GET`
else:
# initial unbound form
I'm using Django 2.0. This is my forms.py:
class PostcodeForm(forms.Form):
postcode = forms.CharField(required=True, widget=forms.TextInput(
attrs={
'placeholder': "enter a postcode",
}
))
def clean_postcode(self):
postcode = self.clean_data.get('postcode', '')
print('clean_postcode', postcode)
if postcode != 'something':
raise forms.ValidationError(_("Please enter a valid postcode"), code='invalid')
return data
And my views.py:
def index(request):
form = PostcodeForm()
context = {
'form': form
}
return render(request, 'index.html', context)
And my index.html:
<form class="form-inline" id="lookup_postcode" action="{% url 'lookup_postcode' %}" method="get">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.postcode.errors }}
{{ form.postcode }}
<button type="submit">Submit</button>
</form>
But when I type in any value other than 'something', the form still submits. I also don't see any print statements in the console, so it looks as though the validator just isn't being run.
What am I doing wrong?
At the moment you are always doing form = PostcodeForm(), for GET and POST requests. That means that the form is not bound to any data, so it will never be valid or have any errors.
In Django, a typical view to process a form looks something like this:
from django.shortcuts import redirect
def index(request):
if request.method == 'POST':
form = PostcodeForm(request.POST)
if form.is_valid():
# form is valid. Process form and redirect
...
return redirect('/success-url/')
else:
form = PostcodeForm()
context = {
'form': form
}
return render(request, 'index.html', context)
For this to work, you'll need to change your form method to 'post'.
<form class="form-inline" id="lookup_postcode" action="{% url 'lookup_postcode' %}" method="post">
If you keep the form method as 'get' then you'll need to bind the form to request.GET instead. You might want to add a check, otherwise you'll get errors for required fields when you first access the index view.
if 'postcode' in request.GET:
# bound form
form = PostcodeForm(request.GET)
else:
# unbound, empty form
form = PostcodeForm()
Use your form as below:
class PostcodeForm(forms.Form):
postcode = forms.CharField(required=True, widget=forms.TextInput(
attrs={
'placeholder': "enter a postcode",
}
))
def clean(self):
postcode = self.cleaned_data.get('postcode', '')
print('clean_postcode', postcode)
if postcode != 'something':
raise forms.ValidationError(_("Please enter a valid postcode"), code='invalid')
return super(PostcodeForm, self).clean()
Everytime you deal with the validity of the posted data, make sure to include form.is_valid() condition in your views.py.
This question may seem like a duplicate but none of the solutions on Google/SO are working, so please do not mark as duplicate.
Here is my view code:
#csrf_protect
def login(request):
if request.POST:
render_to_response('list.tpl', context_instance=RequestContext(request))
else:
# Prepare templates
header = get_template("header.tpl")
body = get_template("login.tpl")
footer = get_template("footer.tpl")
html = header.render(Context({"title": "Login", "charset": "UTF-8"}))
html = html + body.render(Context({}))
html = html + footer.render(Context({}))
return HttpResponse(html)
Here is the login template:
<body>
<div class="bodydiv">
<h3>Login</hd>
<form id="login" method="post" action=".">{% csrf_token %}
User: <input type="text" name="user"><br>
Password: <input type="password" name="password">
<input type="submit" name="submit_login" value="Login">
</form>
</div>
</body>
When I submit the POST request from the form I get CSRF cookie not set.:
I've implemented the four bullets and received the same exact error. What am I missing?
Updated view:
#csrf_protect
def login(request):
print("Method: " + request.method)
if request.method == "POST":
print("IN POST!")
return render(request, 'list.tpl', {})
elif request.method == "GET":
print("IN GET!")
# Prepare templates
header = get_template("header.tpl")
body = get_template("login.tpl")
footer = get_template("footer.tpl")
html = header.render(Context({"title": "Login", "charset": "UTF-8"}))
html = html + body.render(Context({}))
html = html + footer.render(Context({}))
return HttpResponse(html)
You are missing the return. The view is a function and expects you to return an HTTPResponse object.
render_to_response('list.tpl', context_instance=RequestContext(request))
should be
return render_to_response('list.tpl', context_instance=RequestContext(request))
Another thing,
if request.POST
should be
if request.method == 'POST'
Moreover, Avoid using render_to_response. Instead, use render. Source
return render(request, 'list.tpl')
I fixed this issue by using RequestContext instead of Context:
def login(request):
if request.method == "POST":
return render(request, 'login.tpl')
elif request.method == "GET":
# Prepare templates
header = get_template("header.tpl")
body = get_template("login.tpl")
footer = get_template("footer.tpl")
html = header.render(RequestContext(request, {"title": "Login", "charset": "UTF-8"}))
html = html + body.render(RequestContext(request, {}))
html = html + footer.render(Context({}))
return HttpResponse(html)