find out when user leaves a page in django - python

I have an ajax function that sends requests to a Django view every second:
function get_updates() {
$.ajax({
url: full_path,
type: 'GET',
data: {latest_pk: latest_pk},
success: function(json) {
...
},
complete: function(data) {
setTimeout(get_updates, 1000);
}
});
}
get_updates();
get method of the view is like this:
def get(self, request, *args, **kwargs):
if request.GET:
# If there are GET parameters, use them to return updates.
response = self.get_updates(request.GET.get("latest_pk"))
return JsonResponse(response)
else:
# Otherwise if the url is simply requested,
# return the rendered chat page.
return super().get(request, *args, **kwargs)
How can I execute some code in Django, after requests stopped being sent? I need to save the time of the last request.

Try this in javascript there is event called ."beforeunload".
This is just an idea how you can achieve it
<script>
window.addEventListener("beforeunload",function(){
$.ajax({
url: full_path,
type: 'GET',
data: {latest_pk: latest_pk},
success: function(json) {
// add your other logic here
}
});
});
</script>

Related

Django view not getting ajax request

I have a script in my template that tries to send data to a django view during onbuttonclick event. My problem is that the request doesn't seem to make it to the view. The browser console sees the request properly and all, but the django view does't even return true when i call request.is_ajax().
request.method returns GET instead of POST, and the data is empty. This behavior is persistent regardless of the request type.
html
<a onclick="setGetParameter(this)" pid="some_id">Some Text</a>
.js
<script>
var csrftoken = Cookies.get('csrftoken');
function setGetParameter(el){
var stuff = $(el).attr('pid');
$.ajax({
type: 'POST',
headers: { "X-CSRFToken": csrftoken },
url: '/view_url/',
data: {'datatopass': stuff},
success: function(response){
alert(response);
}
});
}
</script>
urls.py
path('view_url/', views.test),
path('', views.home),
views.py
def test(request):
output = request.is_ajax()
return HttpResponse(output)
In Django 3.1 is_ajax() method is deprecated. See Miscellaneous Django 3.1
So for Django >= 3.1 you can do it like that:
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
is_ajax = True
else:
is_ajax = False
And make sure that the following line added in AJAX request headers:
"X-Requested-With": "XMLHttpRequest"
I would be use jQuery click method:
<a pid="some_id">Some Text</a>
<script>
var csrftoken = Cookies.get('csrftoken');
function setGetParameter(el){
var stuff = $(el).attr('pid');
$.ajax({
type: 'POST',
headers: { "X-CSRFToken": csrftoken },
url: '/view_url/',
data: {'datatopass': stuff},
success: function(response){
alert(response);
}
});
}
$(document).ready(function(){
$('a[pid]').click(function(){
setGetParameter(this);
});
});
</script>
Also I would be use JsonResponse objects:
from django.http import JsonResponse
def test(request):
output = request.is_ajax()
return JsonResponse({'is_ajax': output})
In order to serialize objects other than dict you must set the safe parameter to False:
response = JsonResponse([1, 2, 3], safe=False)
After days of beating my head against a wall, I chose to go with a different implementation. It appears I can only render the data on the page that initially sent the request.

Make permission bypass for Ajax requests from my website in Django Rest Framework

I made this API permission
def has_permission(self, request, view):
return request.user.is_authenticated and (
request.user.is_superuser or
models.AllowedToUseAPIList.objects.filter(user=request.user).exists()
)
where I check if user who asks for API is added into list of AllowedToUseAPIList.
But I also need to make AJAX requests from other pages of this website to this API. How can I change the permission to allow doing that?
I also pass my CSRF token into AJAX call but get 403.
I make Ajax call like that:
let csrf = $("input[name='csrfmiddlewaretoken']").val();
...
$.ajax({
url:"{% url 'api:ajax_api:save-mark' %}",
method: 'POST',
data:{
"csrfmiddlewaretoken": csrf,
"name": that.name,
"value": value,
},
success: function (data){
...
}
})
After all, I get 403 Permission Denied.
Try adding a parameter that tells the view when a bypass is allowed:
js:
$.ajax({
url:"{% url 'api:ajax_api:save-mark' %}",
method: 'POST',
data:{
"csrfmiddlewaretoken": csrf,
"name": that.name,
"value": value,
"bypass" : true, // add this parameter
},
success: function (data){
...
}
})
python:
def has_permission(self, request, view):
# check if request was triggered by ajax:
ajax_bypass = 'bypass' in request.POST and request.POST['bypass']
# check if use is a superuser:
user_is_superuser = request.user.is_superuser
# check if user is in allowed list:
user_is_authorized = models.AllowedToUseAPIList.objects.filter(user=request.user).exists()
return ajax_bypass or user_is_superuser or user_is_authorized

Failed to load resource: the server responded with a status of 403 (Forbidden)?

i am posting javascript localstorage object to backend(django). I am passing it through ajax.
this is the code in frontend.
function checkout_(){
console.log("checkout");
for(v in list1){
object=Object.values(localStorage)[v];
object = JSON.parse(object)
}
//ajax here
console.log(object.length);
$.ajax({
url: '{% url "chout" %}',
data: {
'object': object
},
method: "POST",
dataType: 'json',
success: function (data) {
alert("success");
}
});
i have given this function to a button via onclick.
<button class="bg-danger text-white " onclick="checkout_()">Go To Checkout Counter</button>
when i click on this button this error "Failed to load resource: the server responded with a status of 403 (Forbidden)" happens.
in the views.py this is the code.
views.py
def checkoutnow(request):
return render(request, "mart/checkout.html")
I hope this detail is enough to explain the problem..Thankyou
You have to pass csrfmiddlewaretoken also in the post call because of csrf middleware set in the settings
const csrf = "{{ csrf_token }}";
and add this key, value pair to your data:
data: {'csrfmiddlewaretoken':csrf, 'object': object },
You can skip this and just use GET instead of POST if feasible.

Sent data through POST method to show in AJAX request

Ajax method to post and passing a string to the views.py, the post method in the views.py can receive values from ajax but I cannot get the results value to print back in the ajax success method.
I have tried to return HTTPresponse, redirect, render but nothing seem to work for me.
//Ajax//
$("#viewData").click(function(event){
$.ajax({
type: "POST",
data: {
tempData : "permView",
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(result) {
console.log('{{ result }}')
},
});
event.preventDefault()
});
});
//Python//views.py
class SpreadSheetView(TemplateView):
template_name = 'spreadsheet.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {'type': '86'})
def post(self, request):
if request.POST['tempData'] == 'permView':
return render(request, self.template_name, {'result': "test result"})
You are encountering one of these two problems:
You might be getting an error in your view and cannot notice it since you do not cover error case in your ajax request. Just update your ajax request call like this and see if you are getting an error.
You are not specifying dataType parameterto your request, which causes ajax to incorrectly guess your response type.
To cover these two items, update your request such as:
$.ajax({
type: "GET",
dataType : 'html', # or other types, depending on your needs.
data: {
tempData : "permView",
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(data, status) {
console.log(data)
console.log(status)
},
error: function(xhr, status, error) {
console.log(status);
console.log(error);
}
});

ajax json post request to flask

I am struggling to send a ajax post request but cannot figure out where i am going wrong, i have this form which i submit with js and along with that form i want to send the id of a div:
<script type="text/javascript">
$(document).ready(function() {
$('input[type=radio]').on('change', function() {
$(this).closest("form").submit();
var poll_id = $(this).closest("div").attr("id");
var data = {poll_id};
console.log(JSON.stringify(data));
$.ajax({
url: '/poll',
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
dataType: 'json'
}, function(data) {
console.log(data);
});
});
});
</script>
and in flask i try to request it with request.get_json() but keep getting error 400, the form and db.commit() works fine:
#app.route('/poll', methods=['GET', 'POST'])
def poll():
polltodb = pollingresult(request.form['points'])
session['points_session'] = request.form['points']
db.session.add(polltodb)
db.session.commit()
data = request.get_json()
print data
but the get_json() fails.
$(this).closest("form").submit(); tells your html page to submit the form. If any javascript after that line even executes you'd be making a separate XHR request (e.g. 2 requests, the data would never be in the same request using this approach). To accomplish what you're trying to do I'd take a different approach:
Add a hidden element to your form. e.g. <input type="hidden" name="poll_id" id="myHiddenField">
Update your javascript:
<script type="text/javascript">
(function(){
$('input[type=radio]').on('change', function () {
$('#myHiddenField').val($(this).closest("div").attr("id"));
$(this).closest("form").submit();
});
});
</script>
Then, access the data through the form as you normally would and don't worry about get_json()

Categories