Django w/ Apache, CSRF Verification Failing - django

I have a bit of an issue with CSRF verification in my Django app. I have two other {% csrf_token %} tags in my app, in two different HTML templates. These work fine, and always have. When attempting to add a third in another new template though, I receive the '403 Forbidden' page. I've copied the style of the two working 'post' commands exactly, but for some reason this one will not work. Any suggestions?
The 'post' form contains a single select/drop-down object, and a submit button. Clicking the button should direct to a view to process the posted data, written again just like the first 2, but it throws the 403 error instead, with the reason for failure being 'CSRF token missing or incorrect'. I'm running Django 1.4.22 also, with User authentication enabled. Here is the not-working view:
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
...Other Views...
#login_required
def Process(request, id):
...
try:
choice = request.POST['choice']
except(KeyError, Item.DoesNotExist):
return render_to_response('app/home.html', context_instance=RequestContext(request))
else:
...Process posted data...
return HttpResponseRedirect(reverse('app.views.display', args=()))
Here is the working view:
#Same includes/imports as earlier, in same file
#login_required
def Submit(request, id, id_2, data):
try:
new_data = request.POST[data.name]
except(KeyError, DataPoint.DoesNotExist):
return render_to_response('app/home.html', context_instance=RequestContext(request))
else:
...Process new data...
return HttpResponseRedirect(reverse('app.views.Data_View', args=()))
And here is the HTML file:
<!DOCTYPE html>
...
<table>
<tr><td>
<form action="/app/page/to/redirect/to/" method="post">
{% csrf_token %}
<select name="choice">
<option name="yes" value="yes" selected>Yes</option>
<option name="no" value="no">No</option>
</select>
</form></td></tr>...</table>

Related

Django HTML form input to db.sqlite3

I'm making a simple web server to take html input data and insert it to data base table .
I've tried with POST request got into more CSRF troubles , Turned to GET request to go over CSRF (not necessary in my case ) , still not able to GET the html data into Database .
myapp/models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=300, unique=True)
content = models.TextField()
myapp/templates/createpost.html
<head>
<title>Create a Post </title>
</head>
<body>
<h1>Create a Post </h1>
<form action="" method="GET">
{%csrf_token%}
Title: <input type="text" name="title"/><br/>
Content: <br/>
<textarea cols="35" rows="8" name="content">
</textarea><br/>
<input type="submit" value="Post"/>
</form>
</body>
</html>
myapp/views.py
from django.shortcuts import render
from .models import Post
def createpost(request):
if request.method == 'GET':
if request.GET.get('title', None) and request.GET.get('content', None):
post = Post()
post.title = request.GET.get('title', None)
post.content = request.GET.get('content', None)
post.save()
return render(request, 'createpost.html')
else:
return render(request, 'createpost.html')
urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('', TemplateView.as_view(template_name='createpost.html'), name='createpost'),
]
am using Django 2.2.6 with PyCharm community 2019.2.3
I've been searching for almost 2 days , checked django doc , and stackoverflow answers , none was helpful , I had to ask to make sure its not a version related issue and forgive me if i miss understand a simple point am just a beginner.
I've tried with POST request got into more CSRF troubles , Turned to GET request to go over CSRF (not necessary in my case ) , still not able to make it .
Ok.
STOP EVERYTHING RIGHT NOW
Now
do the official Django tutorial and learn to use Django forms and modelforms
read the HTTP spec about the proper use of GET requests (hint: the important word here is "idempotent")
fix your code accordingly
if by then you still have issues with the csrf token, come back and post a question about it (with a proper MCVE etc).
Also note that your question should be claused as either unclear or OT since you didn't explain what your problem is (hint: "doesn't work" doesn't explain anything). But anyway...
What you want (nb: models unchanged) is:
myapp/forms.py
from django import forms
from . models import Post
class PostForm(forms.ModelForm):
class Meta(object):
model = Post
fields = ("title", "content")
views.py
from django.shortcuts import redirect, render
from . models import Post
from . forms import PostForm
def createpost(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.save()
# read the doc for `redirect` and change the destination to
# something that makes sense for your app.
# as to why we redirect, cf https://en.wikipedia.org/wiki/Post/Redirect/Get
return redirect("/")
else:
# GET request, present an empty form
form = PostForm()
return render(request, 'createpost.html', {"form": form})
urls.py
from django.contrib import admin
from django.urls import path, include
# NB: actually you should define myapp's urls in
# myapp/urls.py and `include` them here
from myapp.views import createpost
urlpatterns = [
path('admin/', admin.site.urls),
path('/', createpost, name='createpost'),
]
myapp/templates/createpost.html
<head>
<title>Create a Post </title>
</head>
<body>
<h1>Create a Post </h1>
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Post"/>
</form>
</body>
</html>
I can't garantee this will work out of the box (I'd have to post a full project with proper settings etc to be sure - and actually to test it at least once for typos etc) but that's the correct way of doing things.
I've been searching for almost 2 days
That's 2 days wasted, that you would have better used doing the official Django tutorial. I also suggest you learn to debug programs - just adding a couple ̀€print("XXX")` calls in your view and checking your devserver's outputs would have made clear why nothing got created in your database (hint: with your original urls.py, you are NEVER calling your view function).

Django CMS Aldryn NewsBlog delete Articles from the frontend

I'm trying to get the standard Aldryn Newsblog Buttons working in my Frontend Page. So every User can Add, Delete and Edit Articles(only the articles they created themselves but thats not the question). This is the Menu with the links:
Menu in the Toolbar
So i want to add a Button in my template wich triggers the edit, add or delete prompt: Delete prompt
I hope someone can help me. Thanks in advance.
If you really don't want all employees to see the toolbars, then you're taking on quite a bit of extra work. I would still consider this as an option, as you can apply permissions so that a user can only edit the content you allow, which means that users can take full advantage of Django CMS's built in functionality, which is great.
If you still don't want to take this route then you're going to have to build your own mini admin for your article model. Below I've quickly thrown together an idea for how you can approach this to hopefully help point you in the right direction.
First, your article view should be something like:
from django.views.generic import DetailView
from .models import Article
class ArticleView(DetailView):
context_object_name = 'article'
model = Article
template_name = 'path/to/article.html'
def get_context_data(self, **kwargs):
context = super(ArticleView, self).get_context_data(**kwargs)
context['show_controls'] = (self.request.user.is_authenticated() and
context[self.context_object_name].article == self.request.user)
return context
With the article template like:
<section>
{% if show_controls %}
<div class="controls">
Delete
Edit
</div>
{% endif %}
<article>
...
</article>
</section>
The path to delete view could be a confirm page like the Django admin. So you'd have a view like:
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect, render
from .models import Article
#login_required
def delete_article(request, article_pk):
if request.method == "POST":
article = get_object_or_404(Article, pk=article_pk)
if request.user != article.author:
raise PermissionDenied
article.delete()
return redirect('/redirect/url')
else:
context = {}
...
return render(request, 'path/to/confirm/delete.html', context)
With a template along the lines of:
<section>
<form method="POST">
{% csrf_token %}
<p>Are you sure you want to delete?</p>
<input type="submit" value="Delete">
</form>
</section>
You'd then create a similar setup for the edit page, navigate the user to a page that has a form where the fields can be amended and submitted etc.

Django 1.9: CSRF token missing or incorrect using Stripe

This might be a duplicate but i tried using RequestContext from other answers but it didnt work for me
checkout_test.html:
<form action="" method="POST"> {% csrf_token %}
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_37uDrOYvvyyJSLoV0ziJcYyl"
data-amount="2000"
data-name="Demo Site"
data-description="2 widgets ($20.00)"
data-image="/128x128.png"
data-locale="auto">
</script>
</form>
views.py
def user_review_list(request, username=None, errmsg=None):
return render(request, 'checkout_test.html', {})
so in user_review_list.html, there is a button provided by stripe
when i fill out info and click the button, it raises error:
CSRF token missing or incorrect.
How can i fix this?
I've already tried changing render to render_to_response with RequestContext but that didnt work
You cannot pass your CSRF cookie to Stripe and back. One workaround is to use the #csrf_exempt decorator:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def user_review_list(request, username=None, errmsg=None):
...

Django: issue with a simple form

I'm new at django and I'm having problems with a simple form POST.I have a ModelForm in forms.py and when user enters information in html, views.py taks it and saves it. However, I keep getting an error saying it can't find the view doesn't exist in view.py. Please help me find the error. Thank you!
urls.py
urlpatterns = patterns('',
(r'^mypage/(?P<username>\w+)/$', 'recipeapp.views.my_view'),
forms.py
class NewRecipeForm(forms.ModelForm):
user_info = forms.ForeignKey(User)
title = forms.CharField(min_length=2,max_length=50,required=True,)
post_date = forms.DateField(auto_now=True)
ingredients = forms.TextField(widget=forms.Textarea(),)
picture = forms.ImageField(upload_to='photos/%Y/%m/%d',)
content = forms.TextField(widget=forms.Textarea(),)
views.py
#csrf_protect
from recipeapp.forms import NewRecipeForm
def my_view(request,username):
if request.method == 'POST':
form = NewRecipeForm(request.POST)
if form.is_valid():
form.save()
else:
form = NewRecipeForm()
return render_to_response('postlogin.html',{'username':username},{'form': form}, RequestContext(request))
postlogin.html
<form action="" method="post" id="form">
{% csrf_token %}
<div id="dish-name">
<label><p>Dish name</p></label>
{{form.title}}
</div>
<div id="ingredients">
<label><p>Ingredients</p></label>
{{form.ingredients}}
</div>
<div id="content">
<label><p>Content</p></label>
{{form.content}}
</div>
{{form.picture}}
</form>
Is that really your whole views.py? You have at least three issues:
Firstly, you haven't imported csrf_protect - like any name, a decorator needs to be defined before you can use it.
Secondly, you have to decorate an actual function, not a file. The decorator should go just before the function definition for my_view.
Thirdly, your indentation is broken - the def should not be indented at all.
Given all those, I expect that Python is failing to import your views because of syntax errors.
Also note that you shouldn't really use csrf_protect - you should enable CSRF protection in your middleware (it's on by default) and only use the csrf_exempt decorator, and then only on very very rare occasions.

User Context in Django

I am having problems with user authentication for my django site. I have a log-in screen that seems to work. When the user clicks log-in, I call the django.contrib.auth.login and it seems to work fine. However on subsequent pages have no knowledge that there is a user logged in. Example {% user.is_authenticated %} is false. There are also some menu functions that I want to be available for logged in users such as my-account and logout. Those functions are not available, except on the log-in page. Which is really strange.
This seems to be a user context problem. But I'm not sure how I am supposed to be passing a context around to ensure that my login is stable. Does anyone know at could be going on here? Any advice?
---------part of base.html------------
<!--- The following doesn't register even though I know I'm authenticated -->
{% if user.is_authenticated %}
<div id="menu">
<ul>
<li>My Customers</li>
<li>Customer Actions</li>
<li>My Account</li>
</ul>
</div>
{% endif %}
---------my views.py -----------------
# Should I be doing something to pass the user context here
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
c = Context({
'customer_list': customer_list,
})
t = loader.get_template(template)
return HttpResponse(t.render(cxt))
If you're using Django 1.3, you can use the render() shortcut, which automatically includes RequestContext for you.
from django.shortcuts import render
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render(request, "path_to/template.html",
{'customer_list': customer_list,})
In this case, you could go one step further, and use the generic ListView:
from django.views.generic import ListView
class CustomerList(Listview):
template_name = 'path_to/template.html'
queryset = Customer.objects.all().order_by('lastName')[:5]
Use a RequestContext.
As Daniel Suggested, use the RequestContext... or better, just use the render_to_response shortcut:
from django.template import RequestContext
from django.shortcuts import render_to_response
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render_to_response(
"path_to/template.html",
{'customer_list':customer_list,},
context_instance=RequestContext(request))