I'm trying to send an ajax request to a view called getToken(). I'm not sure why it isn't working. The console outputs "0: ". If I include the code inside my home view which is the page the call is being made from it will change the page to the json output and not the documentid I told it too. It doesn't call getToken at all even though its set up in the urls file to and my ajax url is set to that url.
When a user clicks the create token on his profile it will send a ajax request to getToken and return that output on the page in the output . Thus, the user can then give that key to his friends so they can add him or email or text the key.
HTML
{% load staticfiles %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script {% static "ChompMe/jquery.js" %}></script>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<script type="text/javascript">
$(document).ready(function() {
$("#create_token").click(function() {
var csrf = '{{ csrf_token }}';
$.ajax({
type: 'POST' ,
url: '/gettoken',
datatype: 'json' ,
async: true,
data:{
csrfmiddlewaretoken: '{{ csrf_token }}',
create_token: 'create_token',
},
success: function(json) {
console.log(csrf);
console.log(json.message);
document.getElementById('output').innerHTML = (json.message);
},
error : function(xhr,errmsg,err) {
console.log(xhr.status + ": " + xhr.responseText);
document.getElementById('output').innerHTML = "Token:" + " Request Failed.";
}
});
});
});
</script>
<title>ChompMe
{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
<form method='POST' >
{% csrf_token %}
<button id='create_token' name = 'create_token' value='create_token' > Create Token </button>
</form>
<p id='output'>
Token:
</p>
</body>
</html>
Urls.py
urlpatterns = patterns('',
url(r'^$', 'django.contrib.auth.views.login'),
url(r'^logout/$', logout_page),
url(r'^accounts/login/$', 'django.contrib.auth.views.login'), # If user is not login it will redirect to login page
url(r'^register/$', register),
url(r'^home$', home),
url(r'^register/success/$', register_success),
url(r'^admin/', include(admin.site.urls)),
url(r'^gettoken$', getToken),
url(r'^[A-Za-z0-9_.]+$', friends),
)
Views.Py
#login_required
#csrf_protect
def getToken(request):
print 'getToken'
post_data = request.POST.copy()
username = request.user
if request.POST.has_key('create_token'):
datetimes = datetime.now()
enc_token = base64.urlsafe_b64encode(str(request.user) + str(datetimes))
token = enc_token
context = {'token':token}
return HttpResponse(json.dumps(context),content_type="application/json")
#login_required
#csrf_protect
def home(request):
print 'home'
post_data = request.POST.copy()
username = request.user
if request.POST.has_key('create_token'):
datetimes = datetime.now()
enc_token = base64.urlsafe_b64encode(str(request.user) + str(datetimes))
token = enc_token
context = {'token':token}
return HttpResponse(json.dumps(context),content_type="application/json")
user_data = UserProfile.objects.filter(username=str(request.user))
print user_data
context = {'user': request.user,
'user_data':user_data,
}
return render_to_response('home.html',context , RequestContext(request))
Change /gettoken to /gettoken/.
Related
I am trying to post user geolocation to Django class based view. Apparently, javascript is not so friendly to me. How can I post user geolocation to UserProfileView class based view in django, ajax?
<body>
<div>
<div>
<strong>Current Position: </strong> {{ profile.user_location }}<br/>
</div>
<label for="locations-status">Enable Location?</label>
<input type="checkbox" id="locations-status">
<form id="location_form" method="POST" action="{% url 'rent_app:add-location' %}">
{% csrf_token %}
<button type="button" id="send-my-url-to-django-button">Send URL to Django View</button>
</form>
{% block js %}
<script>
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
}
}
});
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
function (position) {
console.log('Position has been set successfully');
console.log(position.coords);
dataToSend = {
"permission": $("input[name=locations-status]").is(':checked'),
"user_location": position,
};
});
}
$("#send-my-url-to-django-button").click(function() {
$.ajax({
type: "POST",
dataType: 'json',
url: "{% url 'rent_app:add-location' %}",
data: JSON.stringify(dataToSend),
success: function (msg) {
console.log('Succeeded!');
},
error: function (err) {
console.log('Error!');
}
});
}, function (error) {
console.log('Position could not be obtained.');
}
);
</script>
{% endblock %}
</body>
views.py:
class UserProfileView(View):
form_class = UserProfileModelForm
template_name = "user_profile.html"
def get(self, *args, **kwargs):
form = self.form_class()
user_locations = UserProfile.objects.user_location()
return render(self.request, self.template_name,
{"form": form, "user_location": user_locations})
def post(self, *args, **kwargs):
if self.request.is_ajax and self.request.method == "POST":
form = self.form_class(self.request.POST)
if form.is_valid():
instance = form.save()
ser_instance = serializers.serialize('json', [ instance, ])
# send to client side.
return JsonResponse({"instance": ser_instance}, status=200)
else:
return JsonResponse({"error": form.errors}, status=400)
return JsonResponse({"error": ""}, status=400)
The context is {"form": form, "user_location": user_locations}) you don't have any profile passed in the context. I think you need to use {{ user_location }} instead of {{ profile.user_location }}
Just make the javascript work. Thank you, that would be helpful.
Having a tough time with this. I'm sending some data via Ajax to my Flask server route where it is being processed, with hopes to then render a new template with the processed data. The data seems to be flowing fine from my Javascript to my Flask server. (I am using JSGlue for Flask.url_for.) But as soon as it gets to "return render_template" it just dies. I get no traceback errors or anything. I've tried print() and console.log all over the place to get some kind of idea of what is killing it, but so far I've come up empty. Am I missing something obvious?
mypage.js
let c_list = [1,2,3....];
$.ajax({
url: Flask.url_for('get_genres'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(c_list),
success: function (data) {
console.log(data);
}
})
init.py
#app.route('/get_genres', methods=["GET", "POST"]
def get_genres():
if request.method == "POST":
categories = request.json
c = Querybuilder()
genres = c.genres_from_c(categories)
return render_template("genres.html", genres=genres)
index.html
<head>
{{ JSGlue.include() }}
</head>
<body>
{% block body %}
{% endblock %}
</body>
genres.html
{% extends "index.html" %}
{% block body %}
<div class="genre_list">
{% for genre in genres %}
<a href="#" src="{{ genres[genre] }}" class="unclicked" onclick="toggleClicked(this)">
<p>{{ genre }}</p></a>
{% endfor %}
NEXT
</div>
{% endblock %}
After A LOT of digging around, I finally managed to find a solution to this issue. Adding a success function to the ajax call that redirects to another route.
mypage.js
$.ajax({
url: Flask.url_for('genre_picks'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(genres),
success: function(response) {
window.location.href = response.redirect
}
});
init
#app.route('/genre_picks', methods=["POST", "GET"])
def genre_picks():
if request.method == "POST":
genres = request.json
return jsonify({'redirect': url_for("example", path=genres)})
#app.route('/example/<path>')
def example(path):
genres = path
return render_template("example.html", genres=genres)
I followed the instructions of this tutorial
https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html
to check "User already exists or not" but Django still rejecting my POST request. I could use some help complying with Django's CSRF protection mechanism via my AJAX post. I've followed the directions here:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
But it didnt help me. It is my result in console:
{% extends 'base.html' %}
{% block title %}
Register
{% endblock %}
{% load crispy_forms_tags %}
{% block body %}
<div class="container">
<h1 class="text-center">Regiser</h1>
<form class="form-group" method="POST" data-validate-username-url = "{% url 'validate_username' %}">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="Register" class="btn btn-primary text-center" value="Register">
</form>
</div>
{% endblock %}
{% block script %}
<script>
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function() {
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
$("#id_username").change(function() {
var form = $(this).closest("form");
$.ajax({
url: form.attr('data-validate-username-url'),
data: form.serialize(),
dataType: 'json',
success: data => {
if (data.is_taken) {
alert(data.error_message);
}
}
});
});
</script>
{% endblock %}
GET http://127.0.0.1:8000/ajax/validate_username?csrfmiddlewaretoken=kc6NtBw1pch0jjI0SGHhCVBeAKYWZrppOFgxHUaisCVqJUUlY73orIM3PDI0kejA&username=Tony&email=&password1=&password2= 500 (Internal Server Error)
send # jquery-3.5.0.min.js:2
ajax # jquery-3.5.0.min.js:2
(anonymous) # (index):79
dispatch # jquery-3.5.0.min.js:2
v.handle # jquery-3.5.0.min.js:2
FieldError at /ajax/validate_username
Cannot resolve keyword 'username_iexact' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, orders, password, user_permissions, username
Request Method: GET
Request URL: http://127.0.0.1:8000/ajax/validate_username?csrfmiddlewaretoken=kc6NtBw1pch0jjI0SGHhCVBeAKYWZrppOFgxHUaisCVqJUUlY73orIM3PDI0kejA&username=Tony&email=&password1=&password2=
Django Version: 3.0.5
Exception Type: FieldError
Exception Value:
Cannot resolve keyword 'username_iexact' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, orders, password, user_permissions, username
Exception Location: C:\Users\Le Dai Thang\Envs\myproject\lib\site-packages\django\db\models\sql\query.py in names_to_path, line 1483
Python Executable: C:\Users\Le Dai Thang\Envs\myproject\Scripts\python.exe
Python Version: 3.7.7
Python Path:
['C:\Users\Le Dai Thang\Lecture7\project3',
'C:\Users\Le Dai Thang\Envs\myproject\Scripts\python37.zip',
'c:\users\le dai thang\appdata\local\programs\python\python37\DLLs',
'c:\users\le dai thang\appdata\local\programs\python\python37\lib',
'c:\users\le dai thang\appdata\local\programs\python\python37',
'C:\Users\Le Dai Thang\Envs\myproject',
'C:\Users\Le Dai Thang\Envs\myproject\lib\site-packages']
i'm trying to create something like Google Suggest Tool (via suggest api http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q=query )
I'm listening input changes, and send data go GET:
$("#search_form_input").keyup(function(){
var some_var = $(this).val();
$.ajax({
url: "",
type: "get", //send it through get method
data:{jsdata: some_var},
success: function(response) {
},
error: function(xhr) {
//Do Something to handle error
}
});
After that i'm handling this data and send it to Google API and got response in Python:
#app.route('/', methods=['GET', 'POST'])
def start_page_data():
query_for_suggest = request.args.get('jsdata')
if query_for_suggest == None:
suggestions_list = ['',]
pass
else:
suggestions_list = []
r = requests.get('http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q={}&gl=in'.format(query_for_suggest), 'lxml')
soup = BeautifulSoup(r.content)
suggestions = soup.find_all('suggestion')
for suggestion in suggestions:
suggestions_list.append(suggestion.attrs['data'])
print(suggestions_list)
return render_template('start_page.html', suggestions_list=suggestions_list)
In Jinja trying to print it in HTML dynamically:
<label id="value_lable">
{% for suggestion in suggestions_list %}
{{ suggestion }}
{% endfor %}
</label>
But variable in Jinja doesn't update dynamically and print empty list.
How to print suggestions from list dynamically in HTML?
Working example:
app.py
from flask import Flask, render_template, request
import requests
from bs4 import BeautifulSoup
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/suggestions')
def suggestions():
text = request.args.get('jsdata')
suggestions_list = []
if text:
r = requests.get('http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q={}&gl=in'.format(text))
soup = BeautifulSoup(r.content, 'lxml')
suggestions = soup.find_all('suggestion')
for suggestion in suggestions:
suggestions_list.append(suggestion.attrs['data'])
#print(suggestions_list)
return render_template('suggestions.html', suggestions=suggestions_list)
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html>
<head>
<title>Suggestions</title>
</head>
<body>
Search: <input type="text" id="search_form_input"></input>
<div id="place_for_suggestions"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$("#search_form_input").keyup(function(){
var text = $(this).val();
$.ajax({
url: "/suggestions",
type: "get",
data: {jsdata: text},
success: function(response) {
$("#place_for_suggestions").html(response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
</script>
</body>
</html>
suggestions.html
<label id="value_lable">
{% for suggestion in suggestions %}
{{ suggestion }}<br>
{% endfor %}
</label>
In my users page, i have in place editing with ajax. And when i click edit, it works fine. But when i submit the form, it don't do anything. When i checked, this is the error:
CSRF verification failed. Request aborted.
So, how do I place {% csrf_token %} in my javascript? Please advice.
Thank you.
edit.js:
function bookmark_edit() {
var item = $(this).parent();
var url = item.find(".title").attr("href");
item.load("/save/?ajax&url=" + escape(url), null, function () {
$("#save-form").submit(bookmark_save);
});
return false;
}
$(document).ready(function () {
$("ul.bookmarks .edit").click(bookmark_edit);
});
function bookmark_save() {
var item = $(this).parent();
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val()
};
$.post("/save/?ajax", data, function (result) {
if (result != "failure") {
item.before($("li", result).get(0));
item.remove();
$("ul.bookmarks .edit").click(bookmark_edit);
}
else {
alert("Failed to validate bookmark before saving.");
}
})
return false;
}
save_form.html:
<form id = "save-form" method="post" action="/save/">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Save" />
</form>
user_page.html:
{% extends "base.html" %}
{% block external %}
<script type = "text/javascript" src="{% static "assets/js/bookmark_edit.js" %}"></script>
{% endblock %}
{% block title %} {{username}} {% endblock %}
{% block head %} Bookmarks for {{username}} {% endblock %}
{% block content %}
{% include "bookmark_list.html" %}
{% endblock %}
view.py:
#login_required(login_url='/login/')
def bookmark_save_page(request):
ajax = request.GET.has_key('ajax')
if request.method == 'POST':
form = BookmarkSaveForm(request.POST)
if form.is_valid():
bookmark = _bookmark_save(request, form)
if ajax:
variables = RequestContext(request, {
'bookmarks':[bookmark],
'show_edit':True,
'show_tags':True
})
return render_to_response('bookmark_list.html', variables)
else:
return HttpResponseRedirect('/user/%s/' % request.user.username
)
else:
if ajax:
return HttpResponseRedirect('failure')
elif request.GET.has_key('url'):
url = request.GET['url']
title = ''
tags = ''
try:
link = Link.objects.get(url=url)
bookmark = Bookmark.objects.get(
link=link,
user = request.user
)
title = bookmark.title
tags = ' '.join(
tag.name for tag in bookmark.tag_set.all()
)
except ObjectDoesNotExist:
pass
form = BookmarkSaveForm({
'url':url,
'title':title,
'tags':tags
})
else:
form = BookmarkSaveForm()
variables = RequestContext(request, {
'form': form
})
if ajax:
return render_to_response(
'bookmark_save_form.html',
variables
)
else:
return render_to_response('bookmark_save.html',variables)
You are not sending the server generated csrf_token for the POST to verify the validity of the data. Hence the error.
As a part of the data part of the request, you need to send the token
csrfmiddlewaretoken: '{{ csrf_token }}'
Something like this
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val(),
csrfmiddlewaretoken: '{{ csrf_token }}'
};
Or you could simply do:
var data = $('form').serialize()
if you want to send the whole form as a dictionary
var csrftoken = Cookies.get('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
enter link description here
This is what I use. Not sure if it's applicable in your situation though.
// sending a csrftoken with every ajax request
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
}
});