Call same function on multiple urls django - python

urls.py
url(r'^level/ajax/reload/$', views.ajax_change_status,
name='ajax_change_status'),
url(r'^level/(\d+)/ajax/reload/$', views.ajax_change_status,
name='ajax_change_status'),
url(r'^level/(\d+)/(\d+)/ajax/reload/$', views.ajax_change_status,
name='ajax_change_status'),
In my urls.py i have these urls.Im trying to call an ajax function in my view basically to update the notification badge to 0 after user clicks on the bell icon.The notification badge is in the base.html template.Im calling the url with the name "ajax_change_status" . I want all these urls to call the same ajax funtion.Is it possible to do this or is there a better way?Im getting a 500 server error when i click on the bell icon from the second and third url
My ajax function in views.py:
def ajax_change_status(request):
if request.is_ajax():
try:
Notification.objects.filter(receiver=request.user)
.update(viewed=True)
Addnotify.objects.filter(receiver=request.user)
.update(viewed=True)
FollowNotify.objects.filter(receiver=request.user)
.update(viewed=True)
HubNotify.objects.filter(receiver=request.user)
.update(viewed=True)
return JsonResponse({"success": True})
except Exception as e:
print(e)
return JsonResponse({"success": False})
My ajax jquery:
var clicks = 0;
$("#notify").on('click', function () {
$.ajax({
url: 'ajax/reload/',
data: {
},
success: function (data) {
if (data.success) {
console.log('ajax call success.');
$('#badge').html('0')
$('#headnotify').html('NOTIFICATIONS (0)')
// here you update the HTML to change the active to innactive
}else{
console.log('ajax call not success.');
}
clicks++;
}
});
});
Seems like it is not getting into the ajax function when i try it on the second and third url!!

Each one of those urls should have different names. It's going to be pain to allow for optional url arguments. You'll be much better off (and more sane) if you just name them differently. Your view function probably should allow for those to be passed in though, otherwise what's the purpose of them?
def ajax_change_status(request, param1=None, param2=None):
...
And personally I like using keyword arguments as it better explains the url path, but that's up to you.

Related

Django request.GET.get() returns None every two times

I'm trying to use some ajax request to echange between django views and the templates but i'm experiencing a strange behavior with the request.GET.
Django sends an error saying that the data in parameter of the json.loads(data) shouldn't be NoneType as the result of request.GET.get('selects') seems to be None; but if I try to debug this code, it seems that request.GET.get('selects') returns None every two times.
When requesting request.GET.get('selects') in the console, I get:
None the first time
and '[{"pk":"57226796-0960-428a-88aa-ba4120ad34b4"}]' the second time,
then None again
then '[{"pk":"57226796-0960-428a-88aa-ba4120ad34b4"}]' at the third attempt.
every odd attempt return None....
what do I wrong ?
views.py
class AjaxRenameView(View):
def get(self,request):
#import pdb; pdb.set_trace()
selects=request.GET.get('selects', None)
selects=json.loads(selects)
pks = [ pk['pk'] for pk in selects]
if len(pks)==1:
folder=Folder.objects.filter(pk=pks[0])
spotler=Spotler.objects.filter(pk=pks[0])
if folder:
form=FolderRenameForm(instance=folder)
title=_('rename folder')
elif spotler :
form=SpotlerRenameForm(instance=folder)
title=_('rename project')
context={'form':form,'title':title,'submit':_('rename'),'has_error':False}
html_form = render_to_string('includes/modal_form.html',
context,
request=request,
)
return JsonResponse({'html_form': html_form})
return JsonResponse({'has_error':True, 'message':_('an error has occured while renaming')}, safe=False)
def post(self,request):
pass
folder.js
//...
function ajaxAction(selects,url,next){
// when clicked on item of menu (rename, share, move...)
$.ajax({
type:"GET",
data:{'selects':JSON.stringify(selects),'next':next},
url: url,
dataType:"json",
beforeSend: function () {
$("#Modal .modal-content").empty();
},
success: function (data) {
$("#Modal .modal-content").html(data.html_form);
}
});//ajax
}//function ajaxAction
//...
console
(Pdb) request.GET.dict()
{'selects': '[{"pk":"57226796-0960-428a-88aa-ba4120ad34b4"}]', 'next': '/fr/wf/myfiles/'}
(Pdb) request.GET.get('selects')
(Pdb) request.GET.get('selects')
'[{"pk":"57226796-0960-428a-88aa-ba4120ad34b4"}]'
(Pdb) request.GET.get('selects')
(Pdb) request.GET.get('selects')
'[{"pk":"57226796-0960-428a-88aa-ba4120ad34b4"}]'
well I finally found it.
the click() event that triggered the ajax call was related to the href attribute of an element. And as I didn't halt the execution of the function, the link was activated and a call to the django view without parameters was send...
the ajax call with return false; or e.preventDefault();
I modified the ajax call a little bit :
function ajaxActionMenu(pk_list,url){
$.ajax({
type:'GET',
data:{'pk_list':JSON.stringify(pk_list)},
url: url,
dataType:'json',
success:function(data){
jQuery.each(data, function(index,value){
$("#Modal .modal-body .nav").append('<a class="nav-link" href="'+value["url"]+'">'+value["menuitem"]+'</a>');
});
},
complete: function(){
$("#Modal .modal-body .nav").on("click",".nav-link",function(e){
e.preventDefault(); // prevent the activation of the href link
var urlLink=$(this).attr("href");
ajaxAction(pk_list,urlLink);
$("#Modal").modal("show");
});
}
});
}

Why when I render Django template on ajax, success does not appear on the browser?

My Html page isn't rendered on ajax success when I use console.log() in the js file, the HTML page is printed out in the browser console but not in the browser itself.
kindly check my following code:
views.py:
def Filter_by_Products(request):
if request.is_ajax():
if request.method == 'GET':
print("filter by function!")
filter_brand = request.GET.get('filter_brand')
products_qs, qs_color, qs_size = product.objects.Filter_brand(filter_brand.rstrip(','))
context={
"object_list": products_qs,
'colors': qs_color,
'sizes':qs_size
}
# print(products_qs)
# print(qs_color)
# print(qs_size)
return render(request,"product/products.html",context)
ajax.js:
$.ajax({
url:'/cart/api/filterby/',
method:'get',
data:
{
'filter_brand':str,
},
success: function (data) {
console.log(data)
// location.reload()
},
error: function (error) {
console.log(error)
}
})
After googling on my question, I found that my problem is that I'm trying to mix the server side with the client side and the solution is to send my HTML template using HttpResponse not render function and then by using javascript, I select the HTML page and change content with the new html.
Actually, I didn't understand clearly the problem and why mixing server with client caused that problem and why my code wasn't working from the first time using render, so could you please explain more in details or refer links to me to understand.
also, I'm familiar with Django celery and Redis, if i can use those technologies in that situation, could you just refer to me how to use them.
When i'm working with Django and Ajax, i like to use JsonResponse, a library from django.http. This way, I can pass the status response (200, 500, ...), and the data that will be treated in front.
The problem in your case, is that after you received the response, you are reloading the page.
// location.reload()
As your responde data is an object, you have to define, using javascript, where it will be placed on the screen, for example:
success: function (data) {
console.log(data);
$("#div_object_list").html(data.object_list);
},
No problem in return render(request,"product/products.html",context), it will return a rendered html page's content.
The problem is in your ajax request calling: // location.reload(), referring to w3schools.com it reloads current page only without replacing page's content with returned response.
If you need to replace the entire page with returned response, so your ajax success function should like:
success: function (response) {
var newDoc = document.open("text/html", "replace");
newDoc.write(response);
newDoc.close();
}
If you just need to replace with specific html div, you can do:
success: function(response) {
$('#my-div').html(response);
}

Dynamic variable value on HTML with Django

I'm looking to display a constantly-changing python variable (that's read from a websocket server) onto a HTML file, currently i'm using a Django tag as it follows:
templatetags/mytag.py
from django import template
register = template.Library()
current_value = 0
#register.filter
def c_value(placeholder):
return current_value
#more code that modifies current_value reading from a websocket server
index.html
{% load mytag %}
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( {{ placeholder|c_value }} );
}
, 1000);
}
mytimer();
</script>
#some code from the website
<span id="stuff">Holder</span>
However naturally '{{ placeholder|c_value }}' only outputs the first ever value of 'current_value', which is 0 in this case, and so the source code of index.html ends up being:
source code after '{{ placeholder|c_value }}'
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( 0 );
}
, 1000);
}
mytimer();
</script>
Which is not desired since we would like to print the changing-value of 'current_value' each second.
What is the normal approach for these kind of dynamic texts? Many thanks!
There are a few things you'll need to do to accomplish this behavior.
Set up a URL that returns the value you're interested in. For instance, set up your website so that the URL http://example.com/c_value returns a response with the correct information. It's usually a good idea to return the response in a JSON format; in Django, you can use the JsonResponse class to do this. Suppose you return the text:
{
"c_value": "foo"
}
Change your page so that instead of loading in a variable from a template, it makes a request to the address that you set up. If you're using jQuery, you can use the $.ajax function to do this (or $.getJSON, which is just a shorthand function for $.ajax with only JSON data). You'll probably end up with something like this inside of your timer, assuming that the JSON returned matches the example I gave in step 1. (data will contain the JSON object that you sent from the server).
$.ajax({
dataType: "json",
url: "http://example.com/c_value",
success: function(data) {
$('#stuff').html(data["c_value"]);
}
});

Populating backend script for Django form

I'm trying to create a web front end to do various management tasks with Django. I've never needed a front end but now they want different BU's to be able to utilize them and they need something pretty to press a button on. So what I want to do is:
User inputs form data and submits it
Site access's external script using the post data as args
User is redirected to confirmation page
Right now I can post data and I can run the script with args, I just don't know how to combine the two. Any help or hints on what I should look into would be greatly appreciated. I didn't post snippets because I'd have to sterilize them but upon request I can if it's needed in order to help.
The easiest way to interact directly is to leverage Ajax, whereby you use Ajax Post to send JSON to Django and then handle the arguments as a dict(). Here is an example:
In browser (JQuery/JavaScript):
function newModule() {
var my_data = $("#my_element").val(); // Whatever value you want to be sent.
$.ajax({
url: "{% url 'modules' %}", // Handler as defined in Django URLs.
type: "POST", // Method.
dataType: "json", // Format as JSON (Default).
data: {
path: my_data, // Dictionary key (JSON).
csrfmiddlewaretoken:
'{{ csrf_token }}' // Unique key.
},
success: function (json) {
// On success do this.
},
error: function (xhr, errmsg, err) {
// On failure do this.
}
});
In server engine (Python):
def handle(request):
# Post request containing the key.
if request.method == 'POST' and 'my_data' in request.POST.keys():
# Retrieving the value.
my_data = request.POST['my_data']
# ...
Now all you need to do is to direct your HTML form to call the JavaScript function and communicate the data to the engine.
To redirect the user to another page upon success, you can use this in your success function:
window.location.href = "http://www.example.com";
Which simulates a reaction similar to that of clicking on an anchor tag (link).
Hope this helps.

Django testing ajax endpoint in view

I'm using django-ajax in a django application, and want to do more thorough unit testing of the view that uses it.
My template for a particular view contains the following:
{% block head_js %}
<script type="text/javascript">
$(function() {
$('#progressbar').progressbar({
value: false
});
var checkStatus = function() {
$.ajax({
type: "POST",
url: '/ajax/MyApp/check_provisioning.json',
dataType: 'json',
success: function(data) {
if (data.data.complete != true) {
setTimeout(checkStatus, 3000);
} else {
// We've finished provisioning, time to move along.
window.location.replace('/MyApp/next');
}
}
});
};
checkStatus();
});
</script>
{% endblock %}
In MyApp/endpoints.py I have the function (simplified):
def check_provisioning(request):
# Do some stuff
return {'complete': some_boolean}
Now... As far as I can tell, the view functions just fine, in actual usage.
But when making unit tests, django's test client retrieves the rendered response, but doesn't run anything embedded therein.
Does anyone know a way I can unit test that the view and/or the endpoint function are actually doing what they're supposed to? I would rather not fall back on using the django test framework to set up for a selenium test for the one view in the whole project that uses django-ajax this way.
You could use something like django-casper:
https://github.com/dobarkod/django-casper
I haven't used it, but it appears to be a django-specific python library which interfaces with CasperJS and PhantomJS.
PhantomJS is a web-kit based headless browser that gives a more light-weight alternative to browser automation with selenium.

Categories