Send ajax request to django and update html

Viewed 1127

I am writing a web application with Django that through ajax POST request executes on the server some code written in python, and should retrieve on the client side the output as a JSON and update the HTML partially with javascript. I can send the request to the server and execute the subprocess, also do I retrieve the JSON data but not updated in the HTML but shown as a dictionary to the website without the HTML content. So the last part is not working, and I figured out that for the ajax request when I test it in the view function it returns false. Another problem is that the subprocess has a file as output so I can not catch the stdout from the subprocess

view.py:

def call(request):
    call_form = Call(request.POST)
    print(request.is_ajax())->returns false?
    if call_form.is_valid():
        purity_arg = call_form.cleaned_data['purity']
        chr_sex = call_form.cleaned_data['chromosomal_sex']
        command = "cnvkit.py call -m clonal --purity %s --drop-low-coverage  %s" % ( purity_arg, chr_sex)
        process_call = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE,cwd=sfs.path('cnv_app/call_CNS/'), universal_newlines=True)
        stdout, stderr = process_call.communicate()
        if process_call.returncode and stderr:
            output_call += stdout + '\n'
            output_err_call += stderr + '\n'
        else:
            output_call += stdout + '\n'
            process_call.poll()
        response = {'output_call': output_call, 'output_err_call': output_err_call}
        return JsonResponse(response)

.html:

<h2>Call</h2>
<p>Given segmented log2 ratio estimates (.cns), derive each segment’s absolute integer copy number using either:</p>
{% if call_form %}
<form enctype="multipart/form-data" method="POST" id="post-form" >
    {% csrf_token %}
    {{call_form|crispy}}
    <button type="submit" name="call_submit_button" value="submit">Submit</button>
</form>
{% endif %}
    
<div id="response_msg"></div>
    
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<script src="{% static  'js/js_script_main.js' %}"></script>

urls.py

urlpatterns = [
    path('home/', views.home, name='home'),
    path('cnvPipeline/', views.pipeline, name='cnvkit_pipeline'),
]

.js

$('#post-form').on('submit', function(event){
    event.preventDefault();
    $.ajax({
        url: '',
        type: 'POST',
        data: $(this).serialize(), //{'purity': '0.9', 'chromosomal_sex': 'X'},
        dataType: 'json',
        success: function (data) {
            $(#response_msg).prepend(data.output_call)
        }
    });
});
1 Answers

I could find a solution myself, I followed this tutorial: https://realpython.com/django-and-ajax-form-submissions/ and finally I made my first asynchronous request.

.js

function send_call() {
     $.ajax({
        url: '/ajax_call/',
        type : "POST", // http method
        data : { "purity" : $('#purity-text').val(), "chromosomal_sex" : $('#chr-sex').val() }, // data sent with the post request
        dataType: 'json',
        // handle a successful response
        success : function(json) {
            $('#purity-text').val(''); // remove the value from the input
            $("#results").prepend("<li>"+json.output_call+"</li><li> "+json.output_err_call+"</li>");
        },
        // handle a non-successful response
        error : function(xhr,errmsg,err) {
            $('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
                " <a href='#' class='close'>&times;</a></div>"); // add the error to the dom
            console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        }
    });
};

$('#post-form').on('submit', function(event){
    event.preventDefault();
    console.log("form submitted!")  // sanity check
    send_call()
}); 

forms.py

class Call(forms.Form):
    purity = forms.DecimalField(widget=forms.NumberInput(attrs={'id':'purity-text'}))
    chromosomal_sex = forms.ChoiceField(widget=forms.Select(attrs={'id':'chr-sex'}), choices=Sex_CHOICES, label='Chromosomal sex')

urls.py

path('ajax_call/', views.call, name='ajax_call')

views.py

def call(request):
    call_form = Call(request.POST)
    print(request.is_ajax())
    if call_form.is_valid():
        
        purity_arg = call_form.cleaned_data['purity']
        chr_sex = call_form.cleaned_data['chromosomal_sex']
        command = "cnvkit.py call -m clonal --purity %s --drop-low-coverage  %s -o %s" % (purity_arg, sex_arg)
            process_call = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                            cwd=sfs.path('cnv_app/call_CNS/'), universal_newlines=True)
            stdout, stderr = process_call.communicate()
            #if process_call.returncode and stderr:
            output_call = stdout + '\n'
            output_err_call = stderr + '\n'
            process_call.poll()
        response_data = {'output_call': output_call, 'output_err_call': output_err_call}
        return HttpResponse(
            json.dumps(response_data),
            content_type="application/json"
        )

.html

{% if call_form %}
<form enctype="multipart/form-data" method="POST" id="post-form" >
{% csrf_token %}
{{call_form|crispy}}
<button type="submit" value="submit">Submit</button>
</form>
{% endif %}
<div id="results"></div>

Thank you anyways!

Related