django missing csrf token in javascript .submit() function (non ajax) - javascript

I am using a javascript to send an html form to django.
js looks like this:
document.getElementById("fooform").submit();
and the html form looks like this:
<form class="form-inline" id="fooform" action ="{% url 'foo:doo' %}" method="post">
{% csrf_token %}
<input type="hidden" id="fooinput" value="" />
</form>
the js can write the data into the input field without any problems and also carry out the submit. my problem is using the crsf token.
I have already put the token {% csrf_token %} in every conceivable place. (Before the form, before the js...). in the html code is the token also correct.
django gives me the error:
Reason given for failure:
CSRF token missing or incorrect.
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function passes a request to the template's render method.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
Edit:
The view.py:
def foo_view(request):
print(request.POST)
urls.py:
app_name = 'foo'
urlpatterns = \
[
path('doo', views.foo_view, name='foo_view'),
]

Related

How can I send csrf_token?

Good afternoon!
Please help me send csrf_token to the POST function for an authorized user. The error is, when I do user registration, error comes out: Forbidden (CSRF token missing.): /data/task.
The link to the library is below (there is also a demo project for this link).
https://docs.dhtmlx.com/gantt/desktop__howtostart_python.html
If you are working with Django, you need to add the csrf_token to your registration form
<form method="post">
{% csrf_token %}
// form here
</form>

Send Javascript Push Notification - AFTER Form POST and URL redirection

Use case (Django Project):
I want to log in on my login page -> Therefore I use this form in html (login.html):
<form class="loginform" action="" method="POST">
{% csrf_token %}
<div class="loginform">
{{form.as_p}}
</div>
<br>
<input type="submit" class="btn btn-success loginbtn" value="Login">
</form>
In case of successful log in I will redirect with DJANGO to this URL (localhost/welcome/)-> welcome.html:
LOGIN_REDIRECT_URL = "welcome"
I am able to send javascript notifications with alertify, but only when using simple things such as
click on it or mouseover:
function notification(text) {
console.log(text)
alertify.success(text);
}
I tried it with onsubmit="javascript:notification("")" in the html form tag, however this will
be displayed only BEFORE the URL redirection.
So my question is:
How is it possible to activate /send the push notification AFTER the URL redirection and in
case of successfull POST/ Log in?
I really appreciate your help! Thank you a lot!!
Javascript is client-side. That means your alertify.success(text); will be executed client-side, once server already did his render process.
The authentication process is server-side. So you have to make your server make your alertify a part of the rendered content.
Knowing that, you just have to change your LOGIN_REDIRECT_URL content page to include in it a call to notification:
<!-- your html template comes here -->
<script type="text/javascript">
notification('You are now logged in');
</script>
Be remembered that the notification will then display each time the person visits this page. You may want either to redirect him again, or to introduce a variable in Django to avoid displaying it again.

How to execute file.py on HTML button press using Django?

My goal is to click an HTML button on my Django web page and this will execute a local python script.
I am creating a local web application as an interface to a project. This will not be hosted and will always just run on my local machine. My project is run with a python script (which carries out numerous tests specific to my project). All I need is for a button in my web interface to execute this script on my machine.
I have a template index.html where the whole web page is located. I presume I need to call some form of views function possibly when the button is pressed?
How to execute python code by django html button?
This question suggests:
def index(request):
if request.method == 'GET':
return render(request, 'yourapp/index.html', {'output': ''})
elif request.method == 'POST':
py_obj = mycode.test_code(10)
return render(request, 'yourapp/output.html', {'output': py_obj.a})
I tried this just as a test but nothing happened when I went to the URL (located in the appropriate views.py):
def runtest(request):
print("Hello World")
Popen(['gnome-terminal', '-e', 'echo "Hello World"'], stdout=PIPE)
return
However I don't quite understand if this achieves what I need it to, I am struggling to understand what the answer is suggesting.
Where in the Django framework can I specify a call to a local python script when a button is pressed?
(I have very limited experience with web applications, this is simply just meant to be a simple interface with some buttons to run tests)
You want to try to submit a form on the button click. You can then import the functions you want to run from the script and call them in your view. You then redirect to the same page.
I hope this helps!
index.html
<form method="post">
{% csrf_token %}
<button type="submit" name="run_script">Run script</button>
</form>
views.py
if request.method == 'POST' and 'run_script' in request.POST:
# import function to run
from path_to_script import function_to_run
# call function
function_to_run()
# return user to required page
return HttpResponseRedirect(reverse(app_name:view_name))
Adding to answer above. You can run the function in a different view completely:
<form method="post" action="{% url 'app:view/function' %}">
{% csrf_token %}
<button class="btn btn-danger btn-block btn-round">Perform task</button>
</form>
And render whatever template you want (same template will execute task but seem like nothing has happened). This is handy if you already have a 'POST' form handler.

Django: make a POST request on form submit without reloading the page or rendering to another?

I have been struggling with this problem for more than two days, I have looked at similar questions here and to many documentations but nothing helped me. Basically, I am building a Django web application (where people can add themselves as friends) I am using Django package django-friendship, but I want the following to happen: when a user is in someone else profile, the first can click an 'Add friend' button and a friend request must be sent. But I want to achieve this without reloading the page or rendering to another one. The method that has to be triggered in order to send the request is in views.py. Probably I need to use ajax but in what way? My final goal is the button to perform as an 'Add friend' button in facebook, for example (without reloading).
friend_profile.html
<form action="{% url 'users:fr_request' pk=friend.id %}" method="POST">
{% csrf_token %}
<input type="submit" value="Add friend"/>
views.py
def friendship_add(request, pk):
if request.method == 'POST':
to_user = User.objects.get(pk=pk)
from_user = request.user
try:
Friend.objects.add_friend(from_user, to_user)
except AlreadyExistsError as e:
print('Exception when adding a friend ' + e)
else:
return HttpResponse('You added a friend')
return render(request, 'users/friend_profile.html')
urls.py
urlpatterns = [
url(r'users/(?P<pk>\d+)/send/$', views.friendship_add, name='fr_request'),
]
At the moment when submitting the form, I render the page to users/(?P\d+)/send/ which calls the view method and executes Friend.objects.add_friend, but I want this to happen without going to /send/ page or reloading the current?
This can be easily achieved using jQuery. You may want to assign an id to your form in case there are multiple forms in your page:
<form action="{% url 'users:fr_request' pk=friend.id %}" method="POST" id="friend_form">
{% csrf_token %}
<input type="submit" value="Add friend"/>
The script could then look like that:
$(function() {
$("#friend_form").submit(function(event) {
// Stop form from submitting normally
event.preventDefault();
var friendForm = $(this);
// Send the data using post
var posting = $.post( friendForm.attr('action'), friendForm.serialize() );
// if success:
posting.done(function(data) {
// success actions, maybe change submit button to 'friend added' or whatever
});
// if failure:
posting.fail(function(data) {
// 4xx or 5xx response, alert user about failure
});
});
});
For more information and examples refer to the jQuery.post() documentation.

Creating confirmation dialog pages when Javascript is disabled

I'm using Django and I want my users to confirm that they really want something to be deleted. I'm considering pure Django solution (no Javascript confirmations).
According to what I think,I can create a new page containing "Yes" and "No" buttons. If user presses "Yes", my site will go on and delete the object from the database.
Is it the right way to do deletion without using Javascript? How would you implement the feature if you were me?
I would use Django's built in DeleteView, which will display a confirmation page for an HTTP GET request and perform deletion for an HTTP POST request.
The documentation gives this example:
from django.views.generic.edit import DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author
class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')
I'd recommend reading the documentation for the SingleObjectMixin which explains how to customise the way the view finds the object to delete (the default is to look for an URL keyword argument called pk), and for the TemplateResponseMixin which explains how to customise the template that is used (the default is 'myapp/author_check_delete.html').
This is just one of a number of class-based generic views that make basic operations (displaying a page for a single model instance, for a list of model instances, and handling editing, deletion etc.) very quick and easy to implement.
If you wanted to enhance this with JavaScript later you could always write some unobtrusive JS that detects links to the deletion confirmation page (by looking for a class, or a particular URL) and adds a click handler that pops up a confirmation dialog and then sends a POST request to the URL in the link's href attribute. You would also need to modify the view slightly to return a JSON object when request.is_ajax() is True, so that your JS would know if the deletion had succeeded or failed, which would probably involve overriding one of the methods inherited from the DeletionMixin.
That sounds fine. What I have done a couple of times is to create a confirmation template that can be used anywhere in the application:
{% extends 'base.html' %}
{% block content %}
<div class="confirmation-box">
<p>{{ message }}</p>
<div>
Cancel
<form action="{{ action_link }}" method="post">
<input type="hidden" name="next" value="{{ prev_link }}" />
<input type="submit" value="Send" />
</form>
</div>
</div>
{% endblock %}
You pass to it:
A confirmation message for the user (message)
The url to the page you are in (prev_link)
The url that should be called to perform the action (action_link)
If the user cancels the action, then she/he goes back to the original page.
If the user confirms, then the prev_link is passed as a hidden parameter, so the view can redirect the user to the original page after performing the action (although this is completely optional of course).
Which is pretty much what you propossed in your question.

Categories