Home > Enterprise >  How to call an async function from template?
How to call an async function from template?

Time:12-18

When the user clicks a specific button, I want to call an synchronous function inside the already used view function, but passing a parameter from JavaScript. How can I do it?

Template:

<input  type="checkbox" value="{{ subject.id }}" id="flexCheckDefault{{ subject.name }}" onclick="checkRequisite(this.defaultValue)">

Javascript:

function checkRequisite(id){

}

View:

if request.user.is_authenticated and request.user.groups.filter(name='student'):
    subjects = subject.objects.all()
    async def checkResquisite(id):
        requisite = Requisite.objects.filter(subject_requisite_id=id)
    context = {'subjects': subjects, 'requisite': requisite}
    template = loader.get_template('student/subject/select.html')
    return HttpResponse(template.render(context, request))
elif request.user.is_authenticated and request.user.groups.filter(name='teacher'):
    return render(request, 'admin/home/index.html', {})
else:
    return redirect('login')

CodePudding user response:

I think there are a few misconcepts here. Async functions are called from the frontend to the backend (with ajax, fetch...), not the other way around:

async function checkRequisite(id){
    response = await fetch(...);
}

Also, normally you would have two different views, I believe just as a good practice to have your code more organized and descriptive of what your views do exactly.

def load_template(request):
    ...
    return render(...)

def ajax_view(request):
    ...
    return JsonResponse(...)

But, to answer your question, the code below does the following:

On the template, with every click on checkboxes search which of them are selected take their value (subject.id), push into a list and send that list of IDs to backend using a post request with the fetch API.

There (on the backend), check the type the request method and filter requisite based on that list of IDs.

student/subject/select.html

{% extends 'base.html' %}

{% block content %}
    {% for subject in subjects %}
        <label>{{ subject.name }}</label>
        <input  type="checkbox" value="{{ subject.id }}" id="checkbox" onclick="checkRequisite()">
        <br>
    {% endfor %}
    <hr>
    <div id="demo"></div>

{% endblock %}

{% block script %}
<script>
    async function checkRequisite() {
        var id_list = [];
        var inputs = document.getElementsByTagName("input");
        for(var i = 0; i < inputs.length; i  ) {
            if(inputs[i].type == "checkbox") {
                if (inputs[i].checked) {
                   id_list.push(inputs[i].getAttribute('value'))
                } 
            }  
        }
        
        var payload = {
                subject_ids: id_list,
            };
        var data = new FormData();
        data.append( 'data' , JSON.stringify( payload ) );  
        data.append('csrfmiddlewaretoken', '{{ csrf_token }}');

        await fetch("{% url 'core:load-template' %}", {
            method: 'post',
            body: data
        }).then((response) => {
            return response.json();
        }).then((data) => {
            let element = document.getElementById("demo").innerHTML = '';
            for (let key in data['requisites']){
                let element = document.getElementById("demo").innerHTML  = `<p>Requisite: ${data['requisites'][key]['name']} | Subject: ${data['requisites'][key]['subject']}<p><br>`;
            }
        });
        }
</script>
{% endblock %}

views.py

def load_template(request):
    if request.user.is_authenticated and request.user.groups.filter(name='student'):
        queryset = Subject.objects.all()
        requisite = None

        if request.method == 'POST':
            data = json.loads(request.POST.get('data'))
            requisites = Requisite.objects.filter(subject__id__in=data['subject_ids'])
            response = {}
            for requisite in requisites:
                response[requisite.id] = { 'name': requisite.name, 'subject': requisite.subject.name }
            return JsonResponse({ 'requisites': response })

        return render(request, 'student/subject/select.html', {'subjects': queryset })

    elif request.user.is_authenticated and request.user.groups.filter(name='teacher'):
        return render(request, 'admin/home/index.html', {})
        
    else:
        return redirect('login')

urls.py

from django.urls import path
from core import views

app_name = 'core'

urlpatterns = [
    path('load/template/', views.load_template, name='load-template'),    
]
  • Related