需求:在頁面進行一個表格的渲染 並對錶格中的一些屬性進行排序
解決方法:由於表格內的數據過於龐大 一次渲染肯定要很長很長的時間 而且排序放在前端進行排序也需要很長很長的時間 我們把排序放在後臺 並且減少渲染的數據量,僅渲染頁面上的字值
具體的操作步驟:
1、在view 層寫好datatable 的後臺 這裏需要注意的是:
這個後臺是經過重載的:
代碼中的 all_data 爲在圖表中顯示的數據源(數據源經過處理以後爲普通list) 即發送到前端的數據源 前端的js也會實時的和後臺進行交互 實現數據排序 數據換頁等一系列操作
其中的 propeties 是和後臺的 js 代碼中cloums (列變量)一一進行對應的 在這個需求中主要執行後臺排序的工作 :(工作的步驟:前端點擊排序功能並(監聽下按照何種屬性何種順序 ) 傳輸給後臺 後臺相應到前端 然後根據 order_name = propeties[order_column] 調用all_data = sorted(chain(drugs),key= attrgetter(order_name), reverse = False) 進行排序)
由於是異步渲染 所以肯定不會將要渲染的數據一次性發送到前端的 ,根據all_data[start:start+length] 來進行切片操作(即選擇將要渲染的對象)
將要渲染的 對象發送到前端
class UsersList110Json(BaseDatatableView):
total_records = -1
total_display_records = -1
def get_initial_queryset(self):
print(self.request.GET)
propeties = {#這個地方寫上表格的列序號和真實擡頭之間的對應關係,下面好order_by使用名稱
# '0': 'smiles',
# 將不在需要smiles 進行顯示
'1': 'de_id',
'2': 'logp',
'3': 'mw',
'4': 'h_a',
'5': 'h_d',
}
draw = self.request.GET.get('draw')
# 將要排序的列序號
order_column = self.request.GET.get('order[0][column]')
# 將要排序的方式 即按正序還是逆序
order_dir = self.request.GET.get('order[0][dir]')
start = int(self.request.GET.get('start'))
length = int(self.request.GET.get('length'))
de_id = self.request.GET.get('de_id')
# print('我得到的deid'+ de_id)
print('Ajax get de_id is ------------------->{}'.format(de_id))
# 獲得 list 對象
# drugs = models.LevelTwo.objects.filter(parent_id = de_id)
drugs = models.ChildrenAndGrands.get_children_and_grands(de_id = de_id)
order_name = propeties[order_column]
print('order by --------------->{}'.format(order_name))
# 默認用 升序
all_data = sorted(chain(drugs),key= attrgetter(order_name), reverse = False)
if order_dir == 'desc':
all_data = sorted(chain(drugs),key= attrgetter(order_name), reverse=True)
self.total_records = self.total_display_records = len(all_data)
# 生成將要顯示的圖片
# 調用靜態方法
starts = datetime.now()
was_svg = all_data[start:start+length]
make_ajax_svg(was_svg)
ends = datetime.now()
print('processing svg------lasts: ', (ends - starts).seconds)
# print('all_data [10]------------------->{}'.format(all_data[10]))
return all_data[start:start+length]
# return all_data
def filter_queryset(self, qs):
return qs
def get_context_data(self, *args, **kwargs):
try:
self.initialize(*args, **kwargs)
# prepare columns data (for DataTables 1.10+)
self.columns_data = self.extract_datatables_column_data()
# determine the response type based on the 'data' field passed from JavaScript
# https://datatables.net/reference/option/columns.data
# col['data'] can be an integer (return list) or string (return dictionary)
# we only check for the first column definition here as there is no way to return list and dictionary
# at once
self.is_data_list = True
if self.columns_data:
self.is_data_list = False
try:
int(self.columns_data[0]['data'])
self.is_data_list = True
except ValueError:
pass
# prepare list of columns to be returned
self._columns = self.get_columns()
# prepare initial queryset
qs = self.get_initial_queryset()
# prepare output data
if self.pre_camel_case_notation:
aaData = self.prepare_results(qs)
ret = {'sEcho': int(self._querydict.get('sEcho', 0)),
'iTotalRecords': self.total_records,
'iTotalDisplayRecords': self.total_display_records,
'aaData': aaData
}
else:
data = self.prepare_results(qs)
ret = {'draw': int(self._querydict.get('draw', 0)),
'recordsTotal': self.total_records,
'recordsFiltered': self.total_display_records,
'data': data
}
return ret
except Exception as e:
return self.handle_exception(e)
前端的js代碼如下:
js 代碼用jquery 寫成,也是經過重載的 裏面的order 保證是使用什麼排序 2 表示用 第三列進行排序 asc 表示降序
中間的二維數組 中的第一個數組表示 長度的值 第二個中的數據用來顯示再前端 的選擇框中 如果第二個 數組中的數據變成[’'十個,‘三十個’,‘五十個’] ,前端的對應位置就會顯示爲十個 三十個 五十個
colums 表示列變量 表示再在datatable (表格中的顯示列)
其中有幾個屬性:
orderable 表示能否被排序
searchable 能否被 搜索
visible 是否被顯示在頁面中(默認爲顯示)
最後ajax 部分中的
url 是向後端發送的url 地址(在第二步中會提及 在第三步中會進行 定義)
data 爲向後端發送的數據
// 顯示在 tbody 中的內容
$(document).ready(function() {
var dt_table = $('.datatable').dataTable({
language: dt_language, // global variable defined in html
// 降序還是升序
order: [[ 2, "asc" ]],
// 二維數組,第一個數組用來作爲長度的值,第二個數組用來作爲顯示的選項。
lengthMenu: [[10, 30, 50],['10', '30', '50']],
// 列 變量
columns: [
{
data: 'imgscr',
"width": "400px",
render: function (data, type, row, meta) {
return "<img style = 'width:300px;height:200px;transition:all 1s;' src='" + data + "' />";
//還可以給圖片加上超鏈接
//return "<a href='" + data + "'>" + data + "</a>";
},
orderable: false,
searchable: true,
className: "center"
},
{
data: 'de_id',
orderable: true,
searchable: true,
className: "center",
visible : false,
},
{
data: 'logp',
orderable: true,
searchable: true,
className: "center"
},
{
data: 'mw',
orderable: true,
searchable: true,
className: "center"
},
{
data: 'h_a',
orderable: true,
searchable: true,
className: "center"
},
{
data: 'h_d',
orderable: true,
searchable: true,
className: "center"
}
],
searching: false,
processing: true,
serverSide: true,
stateSave: false,
ajax: {
"url": USERS_LIST_JSON_URL,
"data": function(d){
return $.extend( {}, d, {
de_id : document.getElementById('de_id').innerText
});
}
}
});
});
2、添加前端的 html代碼 用來將list 渲染在前端 這裏我只截取了部分代碼 具體的代碼會在後面貼出
需要注意的是 js 的加載順序 jQuery frist then bootstrap 最後是額外的js
下面又一條 var USERS_LIST_JSON_URL = ‘{% url “users_list_json_110” %}’;在上面步驟的ajax 中會進行提到 在下一步中會進行定義
這個指向的是在後臺實現的 view 的url 將會在下一步進行創建 最終指向的是 上一步 view
<script src="{% static 'js/jquery-3.3.1.js' %}"></script>
<script src="{% static 'js/bootstrap.js' %}"></script>
<script src="{% static "loading/ddv_example_1_10.js" %}"></script>
<script type="text/javascript">
var USERS_LIST_JSON_URL = '{% url "users_list_json_110" %}';
// translations for datatables
var dt_language = {
"emptyTable": "{% trans "No data available in table" %}",
"info": "{% trans "Showing _START_ to _END_ of _TOTAL_ entries" %}",
"infoEmpty": "{% trans "Showing 0 to 0 of 0 entries" %}",
"infoFiltered": "{% trans "(filtered from _MAX_ total entries)" %}",
"infoPostFix": "",
"thousands": ",",
"lengthMenu": "{% trans "Show _MENU_ entries" %}",
"loadingRecords": "{% trans "Loading..." %}",
"processing": "{% trans "Processing..." %}",
"search": "{% trans "Search: " %}",
"zeroRecords": "{% trans "No matching records found" %}",
"paginate": {
"first": "{% trans "First" %}",
"last": "{% trans "Last" %}",
"next": "{% trans "Next" %}",
"previous": "{% trans "Previous" %}"
},
"aria": {
"sortAscending": "{% trans ": activate to sort column ascending" %}",
"sortDescending": "{% trans ": activate to sort column descending" %}"
}
}
</script>
3、添加一條url 用來指向 datableview
url(r'^users_data_110/$', UsersList110Json.as_view(), name="users_list_json_110")
4、值得一提的是 這個頁面在渲染時是分開渲染的
用到了一個url 兩個view 最後又渲染到了同一個template
主線爲url -->普通view -->template
分線爲datatable view----> template
分線的執行過程爲 前端提交ajax 請求 匹配相應 的url url 找到 view 進行後臺操作
分線主要執行的任務 :根據前端的請求週而復始的請求後臺操做
5、最後的附件會加上datatable 的一般使用方法
源碼在:https://github.com/ggkong/django-datatable–demo