Django Ajax Calls — Stunning Crafty Method

Django Ajax Method Caller for Stunning Ajax Calls by Dynamic Import

Baysan
CodeX
3 min readApr 19, 2023

--

Hello everyone. In this article, I am going to write about a method that I saw when I was an intern developer in an erp project which was written in PHP. I implemented that crafty method in Python to use in my Django project. I will be writing that how we can assemble the pieces instead of giving deep details like what importlib is etc.

Photo by Kelly Sikkema on Unsplash

Long story short, what the method does is to call methods under classes by using string paths and pass the parameters if there are any. By using the method, I can easily use AJAX calls and communicate from frontend to backend. This reduces the count for creating views to handle the requests.

Helpers: DynamicImporter Class and get_ajax_result_dict Function

Basically, DynamicImporter class has 2 methods: import_module and import_class.

# helpers/dynamic_importer.py

import importlib

class DynamicImporter:

def import_module(self, module_name):
return importlib.import_module(module_name)

def import_class(self, module_name, class_name):
module = self.import_module(module_name)
return getattr(module, class_name)

We can assign a class to a variable by using the method: DynamicImporter().import_class("apps.book.models", "Book") . To do that we use importlib which is a built-in Python package.

I also have another helper function which is get_ajax_result_dict that I use to generate response dict. It is just a standard to unify the responses and make it easy to encounter them.

# helpers/http.py
def get_ajax_result_dict(
result="false", msg="This is default message!", additional_data=None
):
"""
We use this function in all JSONResponse functions to unify responses
result (str): Response flag, true | false
msg (str): Response message
additional_data (dict): Extra data for result dict
"""
result = {"result": result, "msg": msg}
if additional_data is not None:
result.update(additional_data)
return result

Method Caller View and URL

The view below encounter the ajax requests and we always send our ajax request to this view. This view firstly creates an instance of the class and then assigns its method to a variable to invoke. We use the view below by using the JavaScript function in the next section.

# views.py

@csrf_exempt # from django.views.decorators.csrf import csrf_exempt (optional, you can handle the csrf token with js)
def ajax_method_caller(request):
if request.method == "POST":
module_name = request.POST.get("module_name")
class_name = request.POST.get("class_name")
method_name = request.POST.get("method_name")
args = request.POST.getlist("args[]")

importer = DynamicImporter()
try:
target_class = importer.import_class(module_name, class_name)
instance = target_class()

method = getattr(instance, method_name)
result = method(*args)

return JsonResponse(get_ajax_result_dict("true", "SUCCESS!", {"result": result}))
except Exception as e:
return JsonResponse(get_ajax_result_dict("false", str(e), {"result": None}))

return JsonResponse(get_ajax_result_dict("false", "Request error!"))

You can ask that why you override the “result” in the success response 🥲 It depends on your usage, you can implement whatever you want.

Its simple url.

# urls.py

urlpatterns.append(path("ajax-method-caller/", views.ajax_method_caller, name="ajax_method_caller"))

JavaScript Method Caller

The function below makes a POST request to the ajax_method_caller view.

// helpers.js 

// it requires JQuery

const ajax_method_caller = (
module_name,
class_name,
method_name,
args,
success_func,
err_func
) => {
/*
* module_name: module name of the method
* class_name: class name of the method
* method_name: method name to be called
* args: arguments to be passed to the method
* success_func: function to be called on success
* err_func: function to be called on error
*/
$.ajax({
url: "/ajax-method-caller/",
type: "POST",
data: {
'module_name': module_name,
'class_name': class_name,
'method_name': method_name,
'args': args
},
success: success_func,
error: err_func,
});
}

Applied Example of the Method

You can see an example application of the method below. Now, you can easily use your Python classes by calling from frontend.

ajax_method_caller("apps.datagateway.models",
"DataTable",
"apply_column_action",
[action_type, pk], // these are defined in the template
(res) => {
// success response
get_card_notification(res.result);
location.reload();
},
(err) => {
// error response
get_card_notification(err.msg);
});

Finally

Hopefully, it is helpful and you enjoyed. You can access the code by using the Gist below.

https://gist.github.com/mebaysan/1caf81117633e822a5c7798ffb020a87 | @mebaysan

Regards

--

--

Baysan
CodeX
Writer for

Lifelong learner & Developer. I use technology that helps me. mebaysan.com