Извините за повторение этого вопроса и за интеграцию Ajax, поскольку это очень широкий вопрос, но я просто не могу понять.
У меня есть таблица html с 4k + строками данных, и каждая строка имеет некоторую основную c информацию, такую как имя, адрес, фамилия, телефон, и кнопку, которая запускает модальный bootstrap, который содержит дополнительные данные, такие как phone2, address 2, et c.
Моя проблема в том, что мой модал находится внутри a для l oop вот так -
<tbody>
{% for opp in optika %}
<tr>
<td>{{ opp.example }}</td>
<td>{{ opp.some_field }}</td>
<td>
<button id="testbtn" type="button" class="btn btn-success btn-sm btn-detail"
data-toggle="modal"
data-target="#detalji_modal{{ opp.pk }}"
Detalji
</button>
</td>
...
</tr>
{% include "opportunity/partials/_detalji_modal.html" %}
{% endfor %}
</tbody>
И это модальная деталь -
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
id="detalji_modal{{ opp.pk }}"
aria-labelledby="detalji_modalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="">
<div class="container-fluid">
<h5>{{ opp.... }}</h5>
<p>{{ opp.....title }}</p>
...
</div>
</div>
<div class="modal-footer">
<p style="margin-right: auto">Zahtev uneo/la : {{ opp.... }}</p>
...
...
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
Я передам вид также:
@login_required(login_url='registration/login')
def OptikaList(request):
user_groups = request.user.groups.all()
optika_svi = OpportunityList.objects.all().defer(
...
).filter(opp_type__exact='optika').exclude(opp_status='zakazan', is_locked=True).order_by('eluid',
'-opp_status').exclude(
opp_status='odustao')
optika = [o for o in list(optika_svi)]
counter = 1000
context = {
'optika': optika[:counter],
'broj_poslova': counter,
'ukupno_poslova': optika_svi.count(),
'user_groups': user_groups,
}
#Ajax is not used for now, since idk how to implement it right.
if request.is_ajax():
data = {
'rendered_table': render_to_string('opportunity/get_more_tables.html', context=context,
request=request)}
return JsonResponse(data)
return render(request, 'opportunity/opp_optika.html', context)
И это мой ajax вызов, который является беспорядком -
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
// Our ajax function. Specifically declared as we are
// using it in multiple places
let ajax_function = function () {
fetch_modal();
page_changing = false;
$.ajax({
url: '{% url 'opportunity:optika' %}',
type: "get",
cache: true,
data_type: 'html',
success: function (data) {
console.log("Ajaxed");
var page = dt.page(); // save page we are on
var order = dt.order(); // save ordering
var search = dt.search();
var page_length = dt.page.len();
dt.destroy(); // put table back to new
$('#dataTable').find('tbody').empty().append(data.rendered_table);
dt = $('#dataTable').DataTable(table_options); // Re-init datatable
dt.order(order); // Put back our ordering
dt.search(search);
dt.page.len(page_length);
dt.page(page).draw('page'); // Draw the page
dt.draw(false); // Put in our ordering an all the stuff
if (focused_search) {
$('input[type=search]').first().focus();
console.log('focused');
}
focus_set();
focus_lost();
page_changer();
set_detail_btn();
},
error: function (data) {
console.log("Ajax stopped!");
}
});
};
// Variables to hold our urls to the body and footer views
let body_update_link = '{% url 'opportunity:fetch_body' %}';
let footer_update_link = '{% url 'opportunity:fetch_footer' %}';
// id of opportunity currently in our modal
let modal_opp = false;
// ajax function for getting data for modal
let fetch_modal = function () {
if (modal_opp) {
$('#detalji_modal .modal-body').load(body_update_link, modal_opp.toString());
$('#detalji_modal .modal-footer').load(footer_update_link, modal_opp.toString());
}
};
// function for activating getting modal data on click on details
let set_detail_btn = function () {
$('.btn-detail').click(function () {
modal_opp = $(this).data('opp');
fetch_modal();
});
};
// Set modal_opp to false after our modal has disappeared to avoid
// unnecessary updates of an invisible modal
$('#detalji_modal').on('hidden.bs.modal', function (e) {
modal_opp = false;
});
// A central variable for putting in table options
let table_options = {
// searching: false,
// paging: false
order: [[0, "asc"]]
};
// variable holding our setInterval function so we can disable
// it if we want to
let my_timer;
// variable set to true if we are currently in the filter
let focused_search = false;
// Set our focused_search variable if our filter has focus
let focus_set = function () {
$('input[type=search]').focus(function () {
console.log('HAS FOCUS');
focused_search = true;
clearInterval(my_timer);
my_timer = false;
});
};
// Reset our focused_search variable if our filter loose focus
const focus_lost = function () {
$('input[type=search]').blur(function () {
console.log('LOST_FOCUS');
focused_search = false;
},
function () {
console.log('LOST_FOCUS');
conditional_timer_restart();
focused_search = false;
}
);
};
// Restart our timer
const conditional_timer_restart = function () {
if (!my_timer) {
my_timer = setInterval(ajax_function, 2000);
}
};
// variable set to true if we have changed paging
// needed when we click on our paging select so
// our timer restart raliably
let page_changing = false;
// Function to add some behaviour to our pager
// Will stop reloading page if we click on that select
// Will restart the reloading cycle automatically after 5
// seconds
const page_changer = function () {
$('select[name=dataTable_length]').click(function () {
console.log('Page changer init');
if (page_changing) {
page_changing = false;
} else {
clearInterval(my_timer);
my_timer = false;
setTimeout(conditional_timer_restart, 5000);
}
});
$('select[name=dataTable_length]').change(function () {
console.log('Page changer done');
page_changing = true;
my_timer = setInterval(ajax_function, 5000);
});
$('select[name=dataTable_length]').blur(function () {
console.log('Page changer lost focus');
if (!my_timer) {
my_timer = setInterval(ajax_function, 5000);
}
});
};
set_detail_btn = function () {
$('.btn-detail').click(function () {
modal_opp = $(this).data('opp');
fetch_modal();
});
$('.btn-detail').hover(
function () {
console.log('hovered');
clearInterval(my_timer);
my_timer = false;
},
function () {
console.log('hoveroff ');
conditional_timer_restart();
}
);
};
// Our intial init of the table
let dt = $('#dataTable').DataTable(table_options);
focus_set();
focus_lost();
page_changer();
set_detail_btn();
// my_timer = setInterval(ajax_function, 1000);
});
</script>
функции fetch_body и fetch_footer из views.py -
def fetch_body(request):
id = list(request.GET.keys())[0]
opp = OpportunityList.objects.get(pk=id)
return HttpResponse(
render_to_string('opportunity/partials/_modal_body.html', context={'opp': opp}, request=request))
def fetch_footer(request):
id = list(request.GET.keys())[0]
opp = OpportunityList.objects.get(pk=id)
return HttpResponse(
render_to_string('opportunity/partials/_modal_footer.html', context={'opp': opp}, request=request))
Сама страница требует 5+ секунд для загрузки, и она содержит более 20 МБ данных, что является огромным перебором.
В основном мне нужно, чтобы модальное тело (данные) извлекалось при нажатии на кнопку модального открытия / включения ( testbtn) click.
Или, возможно, загрузить детали (модальные) только для показа объектов с помощью th pagination.
И поскольку я не очень хорошо разбираюсь с Ajax (это все еще сбивает с толку для меня) и jQuery, может кто-нибудь объяснить, пожалуйста, лучший подход для этого (пример будет отличным!).
Спасибо!