簡體   English   中英

如何通過 Ajax 調用更新數據表

[英]How to update a Datatable via Ajax call

每當有人訪問 URL /project_page時,我有一個表格顯示來自 model 的內容。

在該頁面上,用戶可以添加文件,我希望表格能夠實時更新,而無需不斷刷新。

為此,我嘗試實現每隔幾秒更新一次表格內容的 Ajax function。 因為這是幾年前在這里提出的

我認為 function 已實現,我在 Ajax 成功 function 中正確接收data ,但我不知道如何將其“注入”到表中。

在此處輸入圖像描述

我還想知道是否有更優化或 Pythonic 的方式來實現這個結果。

urls.py

path('project_page_ajax/', views.project_page_ajax, name='project_page_ajax'),

views.py

@login_required
def project_page(request):
    
    context = {}
    context['nbar'] = 'projects'
    if request.method == 'POST':
        print(request.FILES)
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            file_hist = form.save(commit=False)
            file_hist.user = request.user
            # file is saved
            file_hist.save()
            file_hist_results = FileHistory.objects.all().filter(user=request.user)
            context['file_hist_results'] = file_hist_results
            print(type(context['file_hist_results']))
            return render(request, 'project_page.html', context)
        print (form.errors)
    else:
        form = UploadFileForm()
    file_hist_results = FileHistory.objects.all().filter(user=request.user)
    context['file_hist_results'] = file_hist_results
    context['form'] = form
    return render(request, 'project_page.html', context)

@login_required
def project_page_ajax(request):
    response = dict()
    if request.method == 'GET':
        file_hist_results = FileHistory.objects.all().filter(user=request.user).values()
        #response.update({'file_hist_results': file_hist_results})
        return JsonResponse({"file_hist_results": list(file_hist_results)})
    return HttpResponse('')

project_page.html (JS部分)

var intervalID = setInterval(updateTable, 10000);

function updateTable()
{
    $.ajax({
        method: "GET",
        url: "/project_page_ajax/",
        success: function(data, textStatus, request) {
            console.log(data); 
        }
    });
}

project_page.html (HTML 部分)

<table id="ittFileUploadTable" class="display nowrap" width="100%">
    <thead>
        <tr class="ittLineItemsTh">
        <th style="text-align:center;">File Name</th>
        <th style="text-align:center;">Submitted</th>
        <th style="text-align:center;">Updated</th>
        <th style="text-align:center;">User</th>
        <th style="text-align:center;">Action</th>
        </tr>
    </thead>
    <tbody>
        {% for histfiles in file_hist_results %}
        <tr>
        <td>{{ histfiles.filename }}</td>
        <td>{{ histfiles.uploaded }}</td>
        <td>{{ histfiles.updated }}</td>
        <td>{{ histfiles.user }}</td>
        <td>
        <button id="delete-itt-file" type="button" class="btn btn-secondary">
        <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-trash-fill" viewBox="0 0 16 16">
        <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"></path>
        </svg>
        </button>
        </td>
        </tr>
        {% endfor %}
    </tbody>
</table>                            

這個問題與 javascript 更相關。但這是我的想法,如何使用 partial_html 解決這個問題。這只是一個想法,但也許 javascript 的人會給出一個漂亮的答案)))。
視圖.py

from django.shortcuts import redirect 
@login_required
def project_page(request):
    
    context = {}
    context['nbar'] = 'projects'
    if request.method == 'POST':
        print(request.FILES)
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            file_hist = form.save(commit=False)
            file_hist.user = request.user
            # file is saved
            file_hist.save()
            return redirect('project_page')
        print (form.errors)
    else:
        form = UploadFileForm()
    file_hist_results = FileHistory.objects.all().filter(user=request.user)
    context['file_hist_results'] = file_hist_results
    context['form'] = form
    return render(request, 'project_page.html', context)

@login_required
def project_page_ajax(request):
    response = dict()
    if request.method == 'GET':
        file_hist_results = FileHistory.objects.all().filter(user=request.user).values()
        return render(request, 'partial_page.html', {'file_hist_results':file_hist_results})

project_page.html

<table id="ittFileUploadTable" class="display nowrap" width="100%">
    <thead>
        <tr class="ittLineItemsTh">
        <th style="text-align:center;">File Name</th>
        <th style="text-align:center;">Submitted</th>
        <th style="text-align:center;">Updated</th>
        <th style="text-align:center;">User</th>
        <th style="text-align:center;">Action</th>
        </tr>
    </thead>
    <tbody>
        {% for histfiles in file_hist_results %}
        <tr>
        <td>{{ histfiles.filename }}</td>
        <td>{{ histfiles.uploaded }}</td>
        <td>{{ histfiles.updated }}</td>
        <td>{{ histfiles.user }}</td>
        <td>
        <button id="delete-itt-file" type="button" class="btn btn-secondary">
        <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-trash-fill" viewBox="0 0 16 16">
        <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"></path>
        </svg>
        </button>
        </td>
        </tr>
        {% endfor %}
    </tbody>
</table>

partial_page.html(只是一個簡單的 html 不要放置任何主體或頭部標簽,僅此創建該文件)

<table id="ittFileUploadTable" class="display nowrap" width="100%">
    <thead>
        <tr class="ittLineItemsTh">
        <th style="text-align:center;">File Name</th>
        <th style="text-align:center;">Submitted</th>
        <th style="text-align:center;">Updated</th>
        <th style="text-align:center;">User</th>
        <th style="text-align:center;">Action</th>
        </tr>
    </thead>
    <tbody>
        {% for histfiles in file_hist_results %}
        <tr>
        <td>{{ histfiles.filename }}</td>
        <td>{{ histfiles.uploaded }}</td>
        <td>{{ histfiles.updated }}</td>
        <td>{{ histfiles.user }}</td>
        <td>
        <button id="delete-itt-file" type="button" class="btn btn-secondary">
        <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-trash-fill" viewBox="0 0 16 16">
        <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"></path>
        </svg>
        </button>
        </td>
        </tr>
        {% endfor %}
    </tbody>
</table>

js

var intervalID = setInterval(updateTable, 10000);

function updateTable()
{
    $.ajax({
        method: "GET",
        url: "/project_page_ajax/",
        success: function(response) {
            $("#ittFileUploadTable").hide(); // first hide the current table
            $("#ittFileUploadTable").append(response); // and append the data
        }
    });
}

解決方案很大程度上取決於 JSON 響應是什么。

HTML

如果您的響應是要顯示的實際 HTML 塊,看起來有點像這樣:

<tr><!-- Some tds --></tr>
<tr><!-- Some tds --></tr>
<tr><!-- Some tds --></tr>
<!-- ... -->
<tr><!-- Some tds --></tr>

然后你可以這樣做:

document.querySelector("#ittFileUploadTable tbody").innerHTML = yourTemplate;

JSON

如果您的數據是 JSON,那么最好創建一個模板 function,如下所示:

function fileUploadRecordTemplate(record) {
    return  `
        <td>record.filename</td>
        <td>record.uploaded</td>
        <td>record.updated</td>
        <td>record.user</td>
        <td>
            <button id="delete-itt-file" type="button" class="btn btn-secondary">
                <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-trash-fill" viewBox="0 0 16 16">
        <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"></path>
                </svg>
            </button>
        </td>
    `;
}

像這樣給你的tbody

let output = [];
for (let record of data) output.push(fileUploadRecordTemplate(record));
document.querySelector("#ittFileUploadTable tbody").innerHTML = yourTemplate;

小提琴

 let index = 1; //t1 function updateT1() { //We generate some HTML, but if you get an HTML from server-side, then you can //skip this part let template = ""; let rows = parseInt(document.getElementById("t1rows").value); for (let i = 0; i < rows; i++) { template += ` <tr> <td>${index++}</td> <td>${index++}</td> <td>${index++}</td> <td>${index++}</td> </tr> `; } //This is the actual operation which refreshes the HTML document.querySelector("#t1 > tbody").innerHTML = template; } //t2 function fileUploadRecordTemplate(record) { return ` <tr> <td>${record.filename}</td> <td>${record.uploaded}</td> <td>${record.updated}</td> <td>${record.user}</td> <td> <button id="delete-itt-file" type="button" class="btn btn-secondary"> <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-trash-fill" viewBox="0 0 16 16"> <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1.5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1.5-.5zM8 5a.5.5 0 0 1.5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"></path> </svg> </button> </td> </tr> `; } function updateT2() { let rows = parseInt(document.getElementById("t2rows").value); let data = []; for (let i = 0; i < rows; i++) { data.push({ filename: index++, uploaded: index++, updated: index++, user: index++ }); } let output = []; for (let record of data) output.push(fileUploadRecordTemplate(record)); document.querySelector("#t2 tbody").innerHTML = output.join(""); }
 <table id="t1"> <thead> <th>First</th> <th>Second</th> <th>Third</th> <th>Fourth</th> </thead> <tbody> </tbody> </table> Number of rows: <input type="number" value="4" id="t1rows"><input type="button" value="OK" onclick="updateT1()"> <table id="t2"> <thead> <th>First</th> <th>Second</th> <th>Third</th> <th>Fourth</th> <th>Fifth</th> </thead> <tbody> </tbody> </table> Number of rows: <input type="number" value="4" id="t2rows"><input type="button" value="OK" onclick="updateT2()">

我找到了解決辦法!

正如@mark_b 所建議的那樣,我使用了數據表 Ajax 而不是 jQuery AJAX

現在它可以工作了,這是我的代碼:

$('#ittFileUploadTable').DataTable( {
    responsive: true,
    autowidth: false,
    destroy: true,
    deferRender: true,
    ajax: {
        url: '/project_page_ajax/',
        type: 'GET',
        data: {},
        dataSrc: ""
    },
    columns: [
        {"data": "fields.filename"},
        {"data": "fields.uploaded"},
        {"data": "fields.updated"},
        {"data": "fields.user"},
        {"data": "pk"},
    ],
    columnDefs: [
        { className: 'text-center', targets: [1] },
        {
            targets: [0],
            class: 'text-center',
            orderable: false,
            render: function (data, type, row) {
                var buttons = '<a href="/media/'+data+'" target="_blank">'+data+'</a>';
                return buttons;
            }
        },
        {
            targets: [-1],
            class: 'text-center',
            orderable: false,
            render: function (data, type, row) {
                var buttons = '<form method="post" action="delete_file/'+data+'/"><button type="submit" class="btn btn-danger"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="white" class="bi bi-trash-fill" viewBox="0 0 16 16"><path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"/></svg></button></form>';
                return buttons;
            }
        },
    ],
    order: [
        [0, 'asc']
    ],
    "pagingType": "numbers",
    dom: 'rt'
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM