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