上传文件后,如何在 Django 中使用 AJAX 更新表(与 JavaScript 链接)?
Posted
技术标签:
【中文标题】上传文件后,如何在 Django 中使用 AJAX 更新表(与 JavaScript 链接)?【英文标题】:After uploading file, How to update table (which is linked with JavaScripts) using AJAX in Django? 【发布时间】:2021-05-27 15:46:26 【问题描述】:在上传文件之前,表格如下所示:
使用 AJAX 上传文件后,需要使用 AJAX 刷新表格(这与一些脚本标签链接):
注意: 这里的主要问题是在AJAX成功请求之后,JavaScripts没有申请tabledata容器。
在views.py中:
@login_required(login_url='/login/')
def upload_csv(request):
form = CsvfileForm(request.POST or None, request.FILES or None)
if form.is_valid():
user = form.save(commit=False)
user.author = request.user
user.file_id = ("FILE" + (uuid.uuid4().hex[:9]).lower())
user.save()
form = CsvfileForm()
obj = CsvFiles.objects.get(Q(activated=False) & Q(on_process=False))
obj.on_process=True
obj.save()
with open(obj.file_name.path,'r') as f:
reader = csv.reader(f)
for i, row in enumerate(reader):
if i==0:
pass
else:
csvdatas.objects.create(
file_link = obj,
file_id=obj.file_id,
author = request.user,
data_id=("ABC"+(uuid.uuid4().hex[:9]).lower()),
year=row[0],
industry_code=row[1],
industry_name=row[2],
rme_size=row[3],
variable=row[4],
value=row[5],
unit=row[6]
)
obj.activated = True
obj.save()
all_datas = csvdatas.objects.filter(author=request.user)
all_table = CsvFiles.objects.filter(author=request.user)
return render(request,'refreshTable.html',locals())
在 RefreshTable.html 中:
<legend>Datas</legend>
<br>
<div id="alert-box1"></div>
<br>
<section id="file_table">
<table id="table_id1" class="display responsive nowrap" style="width=100%;">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
% for i in all_table %
<tr>
<td> i.file_id </td>
<td> i.file_name </td>
<td> i.uploaded </td>
<td><a href=" i.file_name.url " target="_blank">Download</a></td>
<td>
<form method="post" action="% url 'deletefile' i.pk %" id="deleteid">
% csrf_token %
<input type="submit" value="Delete" />
</form>
</td>
</tr>
% endfor %
</tbody>
<tfoot>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Download</th>
<th>Delete</th>
</tr>
</tfoot>
</table>
</section>
<br><br>
<form method="POST" enctype="multipart/form-data">
% csrf_token %
<div class="ButtonsData"></div>
<table id="table_id" class="display responsive nowrap" style="width=100%;">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
% for i in all_datas %
<tr>
<td> i.data_id </td>
<td> i.year </td>
<td> i.industry_code </td>
<td> i.industry_name </td>
<td> i.rme_size </td>
<td> i.variable </td>
<td> i.value </td>
<td> i.unit </td>
<td> i.created </td>
</tr>
% endfor %
</tbody>
<tfoot>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</tfoot>
</table>
</form>
在 Profile.html 中(在这个页面中我们只在 AJAX 成功后追加、refreshTable.html):
<body>
<fieldset>
<div id="alert-box"></div>
<br>
<legend>Upload</legend>
<form id="upload-form" method="POST" enctype="multipart/form-data" action="% url 'uploadcsv' %">
% csrf_token %
upload_form
<button type="submit" class="ui button primary">Upload here</button>
</form>
<div id="progress-box" class="not-visible">
</div>
</fieldset>
<br>
<br>
<fieldset id="fieldTable">
<legend>Datas</legend>
<br>
<div id="alert-box1"></div>
<br>
<section id="file_table">
<table id="table_id1" class="display responsive nowrap" style="width=100%;">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
% for i in all_table %
<tr>
<td> i.file_id </td>
<td> i.file_name </td>
<td> i.uploaded </td>
<td><a href=" i.file_name.url " target="_blank">Download</a></td>
<td>
<form method="post" action="% url 'deletefile' i.pk %" id="deleteid">
% csrf_token %
<input type="submit" value="Delete" />
</form>
</td>
</tr>
% endfor %
</tbody>
<tfoot>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Download</th>
<th>Delete</th>
</tr>
</tfoot>
</table>
</section>
<br><br>
<form method="POST" enctype="multipart/form-data">
% csrf_token %
<div class="ButtonsData"></div>
<table id="table_id" class="display responsive nowrap" style="width=100%;">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
% for i in all_datas %
<tr>
<td> i.data_id </td>
<td> i.year </td>
<td> i.industry_code </td>
<td> i.industry_name </td>
<td> i.rme_size </td>
<td> i.variable </td>
<td> i.value </td>
<td> i.unit </td>
<td> i.created </td>
</tr>
% endfor %
</tbody>
<tfoot>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</tfoot>
</table>
</form>
</fieldset>
在 main.js(AJAX 函数)中:
const uploadForm = document.getElementById('upload-form')
const alertBox = document.getElementById('alert-box')
const progressBox = document.getElementById('progress-box')
$('#upload-form').on('submit',function(event)
event.preventDefault();
progressBox.classList.remove('not-visible')
var formData = new FormData($('#upload-form')[0]);
$.ajax(
type:'POST',
url: '/uploadcsv/',
enctype: 'multipart/form-data',
data: formData,
beforeSend: function()
console.log('before')
alertBox.innerHTML= ""
,
xhr: function()
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>
if (e.lengthComputable)
const percent = (e.loaded / e.total) * 100
progressBox.innerHTML = `<br><div class="progress">
<div class="progress-bar" role="progressbar" style="width: $percent%" aria-valuenow="$percent" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p>$percent.toFixed(1)%</p><br>`
);
return xhr
,
success: function(json)
alertBox.innerHTML = `<div class="alert alert-success" role="alert" style="color:green;">
Successfully uploaded the file.
</div>`
progressBox.classList.add('not-visible')
$('#fieldTable').empty() //we are empty the container
$('#fieldTable').append(json) //the response is refreshTable.html, and we append it
,
error: function(error)
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">
Oops... something went wrong
</div>`
progressBox.classList.add('not-visible')
,
cache: false,
contentType: false,
processData: false,
)
)
在脚本中(这些有数据表脚本链接):
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="% static 'main.js' %" defer></script>
<script src="% static 'deletefile.js' %" defer></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jszip-2.5.0/dt-1.10.23/b-1.6.5/b-colvis-1.6.5/b-flash-1.6.5/b-html5-1.6.5/b-print-1.6.5/cr-1.5.3/r-2.2.7/sc-2.0.3/sp-1.2.2/sl-1.3.1/datatables.min.js"></script>
<script>
$(document).ready(function()
$('#table_id tfoot th').each( function ()
var title = $(this).text();
$(this).html( '<input type="text" style="width:100%;" placeholder="Search '+title+'" />' );
);
$('#table_id').DataTable(
responsive: true,
dom: 'Bfrtip',
buttons: [
extend: 'copy',
exportOptions:
columns: ':visible'
,
extend: 'excel',
exportOptions:
columns: ':visible'
,
extend: 'pdf',
exportOptions:
columns: ':visible'
,
extend: 'print',
exportOptions:
columns: ':visible'
,
extend: 'csv',
exportOptions:
columns: ':visible'
,
'colvis'
//'copy', 'csv', 'excel', 'pdf', 'print','colvis',
],
initComplete: function ()
// Apply the search
this.api().columns().every( function ()
var that = this;
$( 'input', this.footer() ).on( 'keyup change clear', function ()
if ( that.search() !== this.value )
that
.search( this.value )
.draw();
);
);
);
);
</script>
注意: 这里的主要问题是在AJAX成功请求之后,JavaScripts没有申请tabledata容器。
【问题讨论】:
【参考方案1】:您可以使用 destroy()
选项 (Datatables docs) 并重新初始化您的表。我也会使用 jQuery .html()
。
See Live Example
在成功方法中添加以下几行:
$("#fieldTable").html(newHtmlTable);
$('#table_id1').DataTable().destroy()
$('#table_id1').DataTable();
$('#table_id').DataTable().destroy();
$('#table_id').DataTable();
您的 AJAX 方法:
$('#upload-form').on('submit',function(event)
event.preventDefault();
progressBox.classList.remove('not-visible')
var formData = new FormData($('#upload-form')[0]);
$.ajax(
type:'POST',
url: '/uploadcsv/',
enctype: 'multipart/form-data',
data: formData,
beforeSend: function()
console.log('before')
alertBox.innerHTML= ""
,
xhr: function()
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>
if (e.lengthComputable)
const percent = (e.loaded / e.total) * 100
progressBox.innerHTML = `<br><div class="progress">
<div class="progress-bar" role="progressbar" style="width: $percent%" aria-valuenow="$percent" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p>$percent.toFixed(1)%</p><br>`
);
return xhr
,
success: function(newHtmlTable)
alertBox.innerHTML = `<div class="alert alert-success" role="alert" style="color:green;">
Successfully uploaded the file.
</div>`
progressBox.classList.add('not-visible')
$("#fieldTable").html(newHtmlTable);
$('#table_id1').DataTable().destroy()
$('#table_id1').DataTable();
$('#table_id').DataTable().destroy();
$('#table_id').DataTable();
,
error: function(error)
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">
Oops... something went wrong
</div>`
progressBox.classList.add('not-visible')
,
cache: false,
contentType: false,
processData: false,
)
)
【讨论】:
以上是关于上传文件后,如何在 Django 中使用 AJAX 更新表(与 JavaScript 链接)?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django 中使用 Ajax 上传图片? Python