Django - How to realize the function of data query (table)? datatable - client processing

Keywords: Javascript Front-end Django JSON

Background of the problem:

In the author's exercise project, users need to query how many books the current system has entered after login. So this brings the following problems:

  • Query conditions that need to be saved for user input
  • The back end needs to process the query conditions entered by the user and return the corresponding data.
  • Front-end can display data in tabular form
  • Front-end can be sorted in ascending/descending order by specified data items
  • Front-end can specify how many rows of data are displayed on a page of a table

This application scenario exists in almost all back-end applications. So in this article, we will focus on how to deal with the front-end and how to display the back-end data through tables.

Table in Metronic template

There are many form templates in Metronic. You can choose one of them according to your needs. Let's first look at the HTML implementation of Metronic's tables.

<table class="table table-striped table-bordered table-hover table-checkable order-column" id="sample_1">
    <thead>
        <tr>
            <th>
                <label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
                    <input type="checkbox" class="group-checkable" data-set="#sample_1 .checkboxes" />
                    <span></span>
                </label>
            </th>
            <th> Username </th>
            <th> Email </th>
            <th> Status </th>
            <th> Joined </th>
            <th> Actions </th>
        </tr>
    </thead>
    <tbody>
        <tr class="odd gradeX">
            <td>
                <label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
                    <input type="checkbox" class="checkboxes" value="1" />
                    <span></span>
                </label>
            </td>
            <td> shuxer </td>
            <td>
                <a href="mailto:shuxer@gmail.com"> shuxer@gmail.com </a>
            </td>
            <td>
                <span class="label label-sm label-success"> Approved </span>
            </td>
            <td class="center"> 12 Jan 2012 </td>
            <td>
                <div class="btn-group">
                    <button class="btn btn-xs green dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false"> Actions
                        <i class="fa fa-angle-down"></i>
                    </button>
                    <ul class="dropdown-menu" role="menu">
                        <li>
                            <a href="javascript:;">
                                <i class="icon-docs"></i> New Post </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <i class="icon-tag"></i> New Comment </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <i class="icon-user"></i> New User </a>
                        </li>
                        <li class="divider"> </li>
                        <li>
                            <a href="javascript:;">
                                <i class="icon-flag"></i> Comments
                                <span class="badge badge-success">4</span>
                            </a>
                        </li>
                    </ul>
                </div>
            </td>
        </tr>

    </tbody>
</table>

According to the above code, it is easy to understand that the < thead > </thead > tab contains the table title bar. In the title bar of the legend, the first column is a checkbox control. Next is Username/Email/Status/Joined/Actions.
The effect is as follows:


Table effect

In the label < tbody > </tbody > is the table content bar. In the illustration, there are 25 records. There are 25 <tr></tr> in the template file. This tag defines a line in HTML, and one <tr></tr> represents a line.
In the implementation of HTML given in this paper, only one line is reserved in order to reduce the space.

The following contents are included in the Motonics template sample file

<script src="{% static '/global/scripts/datatable.js' %}" type="text/javascript"></script>
<script src="{% static '/global/plugins/datatables/datatables.min.js' %}" type="text/javascript"></script>
<script src="{% static '/global/plugins/datatables/plugins/bootstrap/datatables.bootstrap.js' %}"
            type="text/javascript"></script>

This shows that Metronic uses the DataTable plug-in. After a search, the official website of datatable is here. Portal . The official introduction is as follows:

DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, and will add advanced interaction controls to any HTML table.

Let's ignore the many features of datatable. At present, the problem is how to generate the content of front-end tables according to the actual content of the website, that is, the content of < tr > </tr > tags.

Form content generation using Django template

In the author's exercises, the information of title/publishing house/borrowing times/quantity/author/status/ISBN should be displayed. Then the table content is processed as follows, using django's template language
What about {% for item s in item s%} and {% s end for%} to show data from the server?

<table class="table table-striped table-bordered table-hover table-checkable order-column" id="sample_1">
      <thead>
        <tr>
            <th>
                 <label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
                    <input type="checkbox" class="group-checkable" data-set="#id_booksTable .checkboxes"/>
                    <span></span>
                </label> 
            </th>
            <th> Title</th>
            <th> Press</th>
            <th> Borrowing times</th>
            <th> Number</th>
            <th> author</th>
            <th> state</th>
            <th> ISBN</th>
        </tr>
    </thead> 
    <tbody>
    </tbody>             
    <tbody>
        {% for item in items %}
        <tr class="odd gradeX">
            <td>
                <label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
                    <input type="checkbox" class="checkboxes" value="1"/>
                    <span></span>
                </label>
            </td>
            <td>{{ item.name }}</td>
            <td>{{ item.press }}</td>
            <td>{{ item.lendCount }}</td>
            <td>{{ item.acount }}</td>
            <td>{{ item.author }}</td>
            <td>{{ item.status }}</td>
            <td>{{ item.isbn   }}</td>
        </tr>
        {% endfor %}
    </tbody>

</table>
Django background processing
def get(self, request):
    items = []
    testline = {}

    for i in range(100):
        testline['bookname'] = "Python Web Developing Test-Driven Method"
        testline['press'] = "People's Posts and Telecommunications Publishing House"
        testline['lendCount'] = 4
        testline['amount'] = 5
        testline['author'] = "Harry J.W. Percival"
        testline["importTime"] = "2017/12/29"
        testline["status"] = "busy"
        testline["class"] = "IT"
        testline["isbn"] = 1234567            
        items.append(testline.copy())

    return render(request, 'p_books.html', {'items': items})

Here, I use the for loop to generate 100 test data. Let's take a look at the effect:


Testing effect

The data has come out, but there are the following problems:

  • The first line "No data available in table"
  • 100 rows of data are displayed together, not according to the setting of 20 records on a page.

This shows that my approach is not acceptable to the datatable plug-in.
So what on earth should we do?

HTML implementation
<table class="table table-striped table-bordered table-hover table-checkable order-column" id="sample_1">
      <thead>
        <tr>
            <th>
                 <label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
                    <input type="checkbox" class="group-checkable" data-set="#id_booksTable .checkboxes"/>
                    <span></span>
                </label> 
            </th>
            <th> Title</th>
            <th> Press</th>
            <th> Borrowing times</th>
            <th> Number</th>
            <th> author</th>
            <th> state</th>
            <th> ISBN</th>
        </tr>
    </thead> 
    <tbody>
    </tbody>             
</table>

Note that we don't need to write <tbody> </tbody> here, let the datatable plug-in handle it for us.

js implementation
$(document).ready(function() {

    $("#sample_1").dataTable(
        { 
            searching : false,
            destroy : true,
            "ajax": {
                "url": "book/query/",
                "type": "get",
                "dataSrc":"",
            },
            columns: [
                { },
                { data: 'name' },
                { data: 'press' },
                { data: 'lendCount' },
                { data: 'acount' },
                { data: 'author' },
                { data: 'status' },
                { data: 'isbn' }

            ],
            'columnDefs': [{
                'targets': 0,
                'searchable': false,
                'orderable': false,
                'className': 'select-checkbox',
                'render': function (data, type, full, meta){
                return  '<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline"><input type="checkbox" class="checkboxes" value="1"/><span></span></label>'
                }
            }],                

         }

    );                
});

It is important to note that the option dataSrc is "" in ajax, because we use json array to return data directly in Django implementation.

Django implementation
def get(self,request):
    if request.method == "GET":

        objects = Book.objects.all()
   
        dic = [obj.as_dict() for obj in objects]

        return HttpResponse(json.dumps(dic), content_type="application/json")

as_dict is defined in book model:

class Book(models.Model):
    name = models.CharField(max_length=48)
    author = models.CharField(max_length=24)
    isbn = models.IntegerField()
    status = models.CharField(max_length=12)
    press = models.CharField(max_length=48)
    acount = models.IntegerField()
    lendCount = models.IntegerField()

    def as_dict(self):
        return {
            "name": self.name,
            "author": self.author,
            "isbn" : self.isbn,
            "status" : self.status,
            "press" : self.press,
            "acount" : self.acount,
            "lendCount" : self.lendCount
        }

Note here that you need to define get methods in the corresponding url book/query / and return data in json format.

After such operation, the effect is as follows:


Normal effect

You can see that the data has been transferred from the background to the front desk. And the datatable plug-in has already helped us with paging and sorting functions.

Rethinking

Because client processing is adopted, this method requires the server to send all the data needed to be displayed to the front end at one time. Then there are the following questions:

  • When the database is too large, such as when there are millions of levels of data, the speed of sending json data at one time needs to be verified.
  • After the front end obtains the data at one time, and then paginates, it is cached data processing during the last browse, so the data in front of the user may not be real-time data in the server.

How to solve these two problems, we need to use server processing. Next time I'll talk again.

Reference:

Posted by kraen123 on Sat, 22 Dec 2018 11:51:06 -0800