0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django + datatables & 100万件表示

Posted at

Django + datatables & 100万件表示

Djangoのセットアップ、プロジェクト作成、アプリ作成は他サイトを参照ください

django-datatables-viewなる便利なライブラリが存在するので、ありがたく使わせていただきます

pip install django-datatables-view

今回はajaxのデバッグに便利な、runserverではなく、runserver_plus(django-extensiokn)オプションで開発サーバーを起動

python manage.py runserver_plus 192.168.11.7:8089

urlの設定

dashboard/urls.py

path('list/', views.FileDataTablesView.as_view(), name='ajax_datatable'),

template/common/base.html
<html>
<head>
.........
<link rel="stylesheet" href="https://cdn.datatables.net/2.0.8/css/dataTables.dataTables.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/2.0.8/css/dataTables.bootstrap5.css" />
<script src="//code.jquery.com/jquery-3.5.1.js"></script>
.........
</head>
<body>

{% block content %}{% endblock content %}

{% block javascripts %}{% endblock javascripts %}
<script src="https://cdn.datatables.net/2.0.8/js/dataTables.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.2/moment.min.js"></script>
</body>

</html>

最新バージョンは
https://cdn.datatables.net/releases.html
で確認ください

template/dashboard/index.html
{% extends "common/base.html" %}
・・・・・・・・・・
{% block content %}
<table id="datatable" class="table table-striped fs-10 mb-0">
<thead>
<tr class="bg-white item_table">
  <th style="width: 10%;">種類</th>
  <th style="width: 20%;">ファイル名</th>
  <th style="width: 20%;" class="text-center">アップ日</th>
  <th style="width: 10%;">容量</th>
  <th style="width: 40%;">メモ</th>
</tr>
</thead>
<tbody class="item_table"></tbody>
</table>
{% endblock content %}
{% block javascripts %}
<script>
  var table_option = {
    order: [[5, 'desc']],  //targets:Nのカラムで並べる(ここではid)
    searching: false,      //標準の検索機能を無効(検索機能を設定するのでこっちは無効にする)
    deferRender: true,     //大量データの場合、性能が向上(みたい)
    serverSide: true,      //サーバーサイド連携をおこなう設定
    processing: true,      //tableのレンダリング時に「処理中」を表示(falseでもOK)
    lengthChange: false,   //表示件数選択フォームの無効化(割とウザい)
    pageLength: 100,       //表示件数固定(お好きな数値で)
    pagingType: "numbers", //ページングの表示形態
    ajax: {
      "url": "{% url 'dashboard:ajax_datatable' %}",  //urls.pyで指定したurl設定
      "type": "GET",
      "data": function ( d ) {
         return $.extend( {}, d, {
           "KeywordInput": $("#KeywordInput").val().toLowerCase(),  //検索語を小文字に変換
         } );
       }
    },
    columnDefs: [
      {targets: 0,  data: 'type'},
      {targets: 1,  data: 'file_name'},
      {targets: 2,  data: 'created',
        render: function ( data ) { //データの変換、修飾は関数で処理
            return moment(data).format("YYYY-MM-DD H:mm:ss"); //createdはマイクロ秒、秒単位に変換
        }
      },
      {targets: 3,  data: 'file_size', className: 'text-end pe-5', //classnameでclass指定可能
        render: function ( data ) {
            return Number(Math.floor((data/1024)*10)/10).toLocaleString() + 'Mb';
        }
      },
      {targets: 4,  data: 'memo',
        render: function ( data ) {
            return '' +
                '<div class="row">' +
                '<div class="col-6 text-start"> ' +
                data +
                '</div>'+
                '<div class="col-6 text-end">' +
                '<i class="fas fa-edit"></i>' +
                '</div></div>';
        }
      },
      {targets: 5,  data: 'id', visible :false }, //並べ替えと次画面遷移のGET変数用、visible falseで非表示
    ]
  }

  $(function(){
    $.extend( $.fn.dataTable.defaults, {
		language: {
			url: "https://cdn.datatables.net/plug-ins/2.0.8/i18n/ja.json", //日本語化
		}
	});
    var table=$("#datatable").DataTable(table_option);

    // 再描画
    $('#KeywordInput').bind("keyup change", function(){
      table.draw();
    });

  });
</script>
{% endblock javascripts %}
views.py
from django_datatables_view.base_datatable_view import BaseDatatableView
from django.db.models import Q //Qオブジェクトやっぱ便利


class FileDataTablesView(LoginRequiredMixin, BaseDatatableView):
  model = File
  # 初期表示
  def get_initial_queryset(self):
    return (
      super().get_initial_queryset().
      select_related('custom_user').
      filter(
        deleted__isnull=True,
        custom_user=CustomUser.objects.get(pk=self.request.user.pk),
      )
    )

  # 検索結果
  def filter_queryset(self, qs):
    keyword = self.request.GET.get(u'KeywordInput', None)
    if keyword:
      keywords = keyword.split()
      for search in keywords:
        qs = qs.filter(
          Q(memo__icontains=search) |
          Q(type__icontains=search) |
          Q(created__icontains=search) |
          Q(file_size__icontains=search) |
          Q(file_name__icontains=search)
        )
    return qs

大量データのパフォーマンス

環境
Django 4.2.14
MariaDB 10.5.22
Rocky Linux release 9.3 (Blue Onyx)

ハード
Intel(R) N100 3.4GHz 8GB/256GB

  • 1万件超の場合
    image.png

2024-08-31 16.37.35.gif

  • 10万件超の場合
    image.png
    2024-08-31 16.43.17.gif

  • 100万件超の場合
    image.png

2024-08-31 16.49.03.gif

  • 1,775,038件で検索
    2024-08-31 17.20.27.gif

※ datatablesの最大行数は16,777,216 行(2の24乗)
※ datatablesの最新バージョンは2.1.5(2024-08-31現在)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?