Tabulator PUT 通过 Ajax 到 Django REST 端点 - 减少 Table 到最后编辑的记录

Tabulator PUT via Ajax to Django REST Endpoint - Reduces Table to Last Edited Record

我正在使用 Tabulator 和 Django 来编辑模型。在对单元格进行任何更改后,我使用 setData 对使用 Django REST Framework 创建的 REST 端点进行 Ajax 调用。数据库更新正常。问题是来自服务器的响应仅包含更新的单个记录,这使得制表符数据减少到仅该记录。

我的问题是,如何让 Tabulator 忽略响应,或者让数据在编辑后保持独立?

我对这些东西很陌生(包括 Django,尤其是 JavaScript),如果我错过了一些基本的东西,我深表歉意。

我的制表符代码如下。

  1. function getCookie 是根据 Django 文档 here 中的说明生成一个 CSRF_TOKEN。然后将其作为 'X-CSRFTOKEN': CSRF_TOKEN.
  2. 包含在 header
  3. 变量ajaxConfigPut 用于将方法设置为PUT 并包括如上所述的CSRF_TOKEN。然后在稍后 (table.setData(updateurl, updateData, ajaxConfigPut);) 的 table.setData 调用中使用它。
  4. 最后的函数 ajaxResponse 只是检查响应是否是一个数组(因为 Tabulator 需要一个适合 GET 的数组,但 PUT 响应只是一个单一的 {} 对象。所以此函数强制将 PUT 响应放入由一个对象 [{}].
  5. 组成的数组中
    <div id="example-table"></div>

    <script type="text/javascript">

        // get CSRF token
        // https://docs.djangoproject.com/en/dev/ref/csrf/#acquiring-the-token-if-csrf-use-sessions-and-csrf-cookie-httponly-are-false
        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
                }
            }
            }
            return cookieValue;
        }

        var CSRF_TOKEN = getCookie('csrftoken');

        // set variable to customise ajaxConfig for use in the setData call
        var ajaxConfigPut = {
                method:"PUT", //set request type to Position
                headers: {
                    // "Content-type": 'application/json; charset=utf-8', //set specific content type
                    'X-CSRFTOKEN': CSRF_TOKEN,
                },
        };

        //create Tabulator on DOM element with id "example-table"
        var table = new Tabulator("#example-table", {
            ajaxURL:"{% url 'cust_listapi' %}", // reverse pick up the url since in a django template (?)
            height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
            layout:"fitColumns", //fit columns to width of table (optional)
            columns:[ //Define Table Columns
                {title:"Name", field:"name", width:150, editor:true},
                {title:"Age", field:"age", hozAlign:"center",editor:true},
                {title:"Age_Bar", field:"age", hozAlign:"left", formatter:"progress"},
                {title:"Customer Status", field:"is_customer", hozAlign:"left"},
                // {title:"Favourite Color", field:"col"},
                // {title:"Date Of Birth", field:"dob", sorter:"date", hozAlign:"center"},
            ],
            // see http://tabulator.info/docs/4.6/components#component-cell
            cellEdited:function(cell){ //trigger an alert message when the row is clicked
                console.log("Cell edited in row " + cell.getData().id 
                        + " and column " + cell.getField()
                        + " from " + cell.getOldValue() + " to " 
                        + cell.getValue()
                        + ". The row pk=" + cell.getData().id 
                        );
                console.log(cell.getData());

                var updateurl = "{% url 'cust_listapi' %}" + cell.getData().id + "/"
                console.log('URL is: ' + updateurl)
                // Create variable from full row data but drop the id;
                console.log('About to create updateData')

                var updateData = {};
                updateData[cell.getField()] = cell.getValue();

                console.log(updateData);

                console.log('About to setData');
                table.setData(updateurl, updateData, ajaxConfigPut);
                console.log('Finished setData');
                //cell.restoreOldValue();
            },
            ajaxResponse:function(url, params, response){
                console.log('Beginning ajaxResponse')
                console.log('The type is:', typeof(response));
                console.log(Array.isArray(response))
                console.log(response)
                result = response;
                if(Array.isArray(response) === false){
                    result = [response];
                };
                return result;
            }
        });

    </script>

这是 table 编辑前的截图: Table Before Editing

这是编辑第一行后的屏幕截图(将 'Mabel' 更改为 'Jemima'): Screenshot after editing

控制台日志如下: Console Log

我尝试修改端点的响应,以便对数据库中的所有记录进行 returned,但问题是它不包括编辑,因此制表符 table数据被覆盖。这是我在 Django views.py 中使用的代码。也许有办法 return 已更改的数据? views.py

from rest_framework import generics, mixins

from apps.app_mymodel.models import Customer
from .serializers import CustomerSerializer

class CustomerListAPIView(generics.ListAPIView):
    serializer_class = CustomerSerializer
    queryset = Customer.objects.all()

class CustomerUpdateAPIView(generics.GenericAPIView,
                            mixins.ListModelMixin,
                            mixins.UpdateModelMixin):

    serializer_class = CustomerSerializer
    queryset = Customer.objects.all()

    # Override the put function here to return all records
    def put(self, request, *args, **kwargs):
        # return self.update(request, *args, **kwargs)
        return self.list(request, *args, **kwargs)

这是序列化程序: serializers.py

from rest_framework import serializers
from apps.app_mymodel.models import Customer

class CustomerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = '__all__'

有人能给我指出正确的方向吗?

您的 CustomerUpdateAPIView 使用的

None 个 Mixin 有一个名为 put 的方法。我不认为该函数被调用。相反,您可以尝试覆盖视图集的 update 方法。它可能看起来像这样:

def update(self, request, *args, **kwargs):
    obj = super().update(request, *args, **kwargs)  # performs the update operation
    return self.list(request, *args, **kwargs)

您可以查看此 URL 以了解您正在使用的 类:http://www.cdrf.co/ 在那里您将看到您正在使用的 类 的所有方法,以更好地理解您的请求流程。