从 Django 模型中使用 Ajax 获取模态数据
Posted
技术标签:
【中文标题】从 Django 模型中使用 Ajax 获取模态数据【英文标题】:Fetch modal data with Ajax from Django Model 【发布时间】:2020-07-26 01:21:27 【问题描述】:很抱歉重复这个问题,以及 Ajax 集成,因为它的主题非常广泛,但我就是想不通。
我有一个包含 4k+ 行数据的 html 表,每一行都有一些基本信息,如姓名、地址、姓氏、电话和一个按钮,该按钮触发一个引导模式,其中包含附加数据,如电话 2、地址 2、等等
我的问题是,因为我的模式位于这样的 for 循环中 -
<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>
views.py 中的 fetch_body 和 fetch_footer 函数 -
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 秒以上的时间来加载,而且它有超过 20mb 的数据,这是一个巨大的杀伤力。
基本上我需要在模态打开/按钮(testbtn)点击时获取模态主体(数据)。
或者加载详细信息(模态)仅用于显示具有分页的对象。
而且由于我对 Ajax(它仍然让我感到困惑)和 jQuery 不太好,有人可以解释一下最好的方法(示例会很棒!)。
谢谢!
【问题讨论】:
有很多例子,随便选一个。 ***.com/questions/20306981/… 例如。您的时间问题可能是因为您多次获取对象/您的模板 for 循环不断进行查找,这会花费时间。 docs.djangoproject.com/en/3.0/ref/models/querysets/… 看看那个和values/values_list
。最后但并非最不重要的一点是,我建议对代码中的所有内容(属性、变量、名称等)使用英语。你偷了你的项目变得更大的机会......
我觉得这个链接没用,我已经看过了。我在那里找不到我的问题的好例子。预取相关很好,但我从 db 视图中提取数据,它不是托管的,只有 CharFields,所以这里没有预取相关。我也更喜欢英文,但是这个是可以理解的,因为我删除了所有不必要的代码。
请发布您的 Ajax 调用(js)。也许创建一个单独的 url 和函数来理解这个概念会更容易。想法是在第一个视图中加载一些数据,然后使用 Ajax 调用获取更多数据。一种方法是每次用户打开模式时触发 Ajax 调用,并且在模式中有更多通过 Ajax 加载的数据。另一种方法是只加载 10 个对象,然后滚动加载下一个 10,依此类推。顺便说一句'optika': optika[:counter]
没有意义,如果您想限制查询,请在获取对象时执行此操作。您示例中的计数器始终为 1000?为什么是 int()?
我添加了当前未使用的 ajax 调用。是的,我理解理论上的逻辑,只是不知道如何在我的代码中实现它。
【参考方案1】:
事实证明,Ajax 并不难理解。
所以基本上没有正确答案,你应该选择最适合你的选项。
如前所述,此链接How do I integrate Ajax with Django applications? 为初学者提供了很好的详细说明。
【讨论】:
以上是关于从 Django 模型中使用 Ajax 获取模态数据的主要内容,如果未能解决你的问题,请参考以下文章
Django + ajax + 模态表单 bootstrap5.如何让它发挥作用?