How to call Python functions from JavaScript in Django?

Question:

I’ve been struggling on this for a couple days. I’ve read through many posts, blogs, and watch video demo on Django projects, but nothing quite answers my problem.

I have a Django webapp that uses a Python API to connects to a third-party service to analyze text data. The user writes into a text area, presses the button, then the text is sent to the service which returns a list of JSON objects. The API call to this service is a Python function. I’m trying to use Ajax to make an async call to the Python function using the text data as a param when the button is pressed.

I’m not at this time trying to invoke my third-party service, yet. I’m just trying to see if I can get a response from Python sending input and receiving output.

Most of the examples I’ve found involve creating a form and submitting it so the Django framework automatically calls it’s Python functions. A form is not exactly what I’m trying to build, nor am I wanting to proceed to a new page to see the results or refresh the current one.

<!-- index.html -->
<html>
<head>
    <title>Test Data</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script>

        document.getElementById("Button").addEventListener('click', analyzeText());

        function analyzeText(){
            var text = document.getElementById('text-to-analyze').value;

            $ajax({
                type: "POST",
                url: "/models.py",   /* Call python function in this script */
                data: {param: text},   /* Passing the text data */
                success: callback
            });
        }

        function callback(response){
            console.log(response);
        }
    </script>
</head>
<body>
    <textarea id="text-to-analyze" rows="12" cols="100"></textarea><br>
    <button id="button" value="Analyze"/>

</body>
</html>


# models.py
from django.db import models

# Function I want to call from Ajax
def testcall():
    return 'test successfull'

EDIT:
I almost have it working. I’m just getting syntax errors with ajax I can’t figure out.

Could not parse the remainder: ‘ ‘ajax-test-view” from ‘url ‘ajax-test-view”

EDIT
I fixed all the syntax errors but now I’m getting 404 errors when trying to execute the target python script. I now understand how url and pathing works in Django, but using Kostadin Slavov’s solution, how can I do this without routing to a specific html?

In the ajax, I’m setting the url like this:
url: '{{ 'ajax-test-view' }}',
And in my python I have the url pattern set like this:
path(r'^django-app/$', views.testcall, name = 'ajax-test-view'),

It seems like the variable in the ajax url points to the name field in the url pattern, but that also seems to be the name of a specific html file to render(?) Or is it the name of the py function?

When I click my button the ajax sends a command to http://localhost:8000/what-ever-the-name-field-is-in-the-url-pattern and I get a 404 from it. Is the framework trying to load a page or does it mean it can’t find my python file?

Derp… It’s important to know that url: '{{ 'ajax-test-view' }}', is the url address ajax will request and Django’s url dispatcher intercepts it to do something else only if the path matches perfectly.

FINAL EDIT
Got it working. A couple things I changed in Kostadin Slavov’s solution:

# urls.py
urlpatterns = [
   url(r'^$', views.index, name = 'index'),
   path('my-ajax-test/', views.testcall),
]

<!-- index.html -->
<script>
....

var text = "test successful";

$.ajax({
   type: "POST",
   url: '{{ 'my-ajax-test/' }}',
   data: { csrfmiddlewaretoken: '{{ csrf_token }}', text: text },
   success: function callback(response){
               console.log(response);
            }
});
</script>

# views.py
def testcall(request):
   return HttpResponse(request.POST['text'])
Asked By: GhostRavenstorm

||

Answers:

in the urls.py you create an url

path('my-ajax-test/', views.myajaxtestview, name='ajax-test-view'),

then your ajax should loook like

pay attention to the csrf_token otherwise will send you an error

        $ajax({
        type: "POST",
        url: '{{ url 'ajax-test-view'}}',   
        data: {csrfmiddlewaretoken: '{{ csrf_token }}',
              text: "this is my test view"},   /* Passing the text data */
        success:  function(response){
               alert(response);
           }
    });

in views.py

def myajaxtestview(request):
    return HttpResponse(request.POST['text'])

Summary:

you need to create the url in your urls.py which leads to your views.py
then the view gets the data that you’ve sent in the request.POST in the request you have plenty of data you can find more about it here.
in your case you are more interested in request.POST it’s a python dictionary
so you pick the parametre that you have send and work with it
you may play with it like return HttpResponce('test'+ request.POST['text'])

If you want to get something from models.py let’s say you data that you sent from the js is {object_type: hammer}

def myajaxtestview(request):
    look_for = request.POST['object_type']
    #lets say you have model Items
    my_items= serializers.serialize('json', Items.objects.filter(object_type=look_for))
    return JsonResponse(my_items)
Answered By: ThunderHorn

What you are trying is a well known problem. When you do ajax request to the server , the server responds with some data or may be renders a template.

For this request – response cycle to work, you will have to create a mapping of the url to the controller logic. You will have to create a url and a python function mapping in urls.py.
The python function will be in views.py. Now when you request for that url with the given method(POST or GET), it will call the mapping function and return the result.

Answered By: himank

After reading the question edits and the different answers, this is
what worked for me (doesn’t include imports):

File: urls.py

#urls.py
urlpatterns = [
   path('', views.index, name = 'index'),
   path('my-ajax-test/', views.testcall),
]

File: index.html

#index.html
<html>
<head>
    <title>Test Data</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script>

        function analyzeText(){
            var text = document.getElementById('text-to-analyze').value;

            $.ajax({
                type: "POST",
                url: '{{ 'my-ajax-test/' }}',
                data: { csrfmiddlewaretoken: '{{ csrf_token }}', text: text },  
                success: function callback(response){
                           /* do whatever with the response */
                           alert(response);
                        }
            });
        }
    </script>
</head>
<body>
    <textarea id="text-to-analyze" rows="12" cols="100"></textarea><br>
    <input type="submit" id="button" value="process" onclick="analyzeText();">

</body>
</html>

File: views.py

#views.py
def index(request):
   return render(request, 'vote/index.html')

def testcall(request):
   #Get the variable text
   text = request.POST['text']
   #Do whatever with the input variable text
   response = text + ":)"
   #Send the response 

   return HttpResponse(response)
Answered By: HLeb

I struggled with this issue for a day or two. Here’s what solved my problem.

EDIT: I also needed to download the full version of jquery to get the ajax request working.

HTML

In your HTML you need to add {% csrf_token %} to your form

<form id="your_form">
    {% csrf_token %}  //include the csrf_token line in your form
    <div>
        <input type="submit" value="blah blah blah">
    </div>
 </form>

script.js

For your java script code add this function to get the csrf cookie.

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;
}

Next you need to add the csrf token into your ajax request as follows.

    var csrftoken = getCookie('csrftoken');

    $.ajax({
       type: "POST",
       url: '/my-url/', --your url here
       data: { csrfmiddlewaretoken: csrftoken, text: "your text data here" },
       success: function callback(response){
                   console.log(response);
                }
    });
Answered By: Michael Wheeler

Use AJAX

Add this in your html file

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Then use this in your js file

$.ajax({
      type: "POST",
      url: "Your defined route in urls.py file", #then in your views.py you can define your operations 
      data: {
        csrfmiddlewaretoken: '{{ csrf_token }}',
        text: your_input
      },   /* Passing the text data */
      success: function(response) {
        alert(response); #response form your request
      }
    });

You have to receive this post request in your views.py file as:

request.POST.get("key")
Answered By: Vivek Gupta
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.