Как вызвать асинхронную функцию из шаблона?

Когда пользователь нажимает определенную кнопку, я хочу вызвать синхронную функцию внутри уже используемой функции представления, но передавая параметр из JavaScript. Как я могу это сделать?

Шаблон:

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

Javascript:

function checkRequisite(id){

}

Вид:

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')

Мне кажется, здесь есть несколько неверных концепций. Асинхронные функции вызываются из фронтенда в бэкенд (с помощью ajax, fetch...), а не наоборот:

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

Кроме того, обычно у вас есть два разных представления, я считаю, что просто в качестве хорошей практики, чтобы ваш код был более организован и описывал, что именно делают ваши представления.

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

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

Но, чтобы ответить на ваш вопрос, приведенный ниже код делает следующее:

В шаблоне при каждом нажатии на чекбоксы искать, какие из них выбраны, брать их значение (subject.id), заталкивать в список и отправлять этот список ID в бэкенд с помощью post запроса с fetch API.

Там (на бэкенде) проверьте тип метода запроса и отфильтруйте реквизит на основе этого списка ID.

student/subject/select.html

{% extends 'base.html' %}

{% block content %}
    {% for subject in subjects %}
        <label>{{ subject.name }}</label>
        <input class="form-check-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'),    
]
Вернуться на верх