Data Tablesの表中にリンクを埋め込む
はじめに
django-datatables-viewを使ってAjaxで便利な一覧を作ることには成功したものの、そのままだと使いにくい。なぜなら一覧から詳細画面に遷移する、などのリンクがなかったから。これはどうしても必須だったので、調べて実装した。以下の記事の続きの位置づけ。
結論
「render_column」をオーバーライドして、指定の項目のときだけreturnを変えるようにする。 ソースはこちら。
実装としては以下の通り。
class BookJsonView(BaseDatatableView): model = Book columns = ['id', 'title', 'author'] def render_column(self, row, column): if column == 'id': return f'<a href="/sample/bookdetail/{row.id}">{row.id}</a>' else: return super(BookJsonView, self).render_column(row, column)
「id」のときだけ、リンクとなるようにHTMLのタグをreturnした。
get_absolute_url()の定義でもうまくいくと思いきや・・・
django-datatables-viewのソースを見たところ、Modelにget_absolute_url()メソッドが書いてあると aタグとして返すように書いてある。
def render_column(self, row, column): """ Renders a column on a row. column can be given in a module notation eg. document.invoice.type """ value = self._render_column(row, column) if value and hasattr(row, 'get_absolute_url'): return format_html('<a href="{}">{}</a>', row.get_absolute_url(), value) return value
ほうほう、なるほど、きっとこっちの実装のほうがif文で拾う必要もなくキレイになるなぁと思い試した。
models.py
from django.db import models from django.urls import reverse class Book(models.Model): """本""" class Meta: db_table = 'book' title = models.CharField(verbose_name="本のタイトル", max_length=255) author = models.CharField(verbose_name="著者", max_length=255) def get_absolute_url(self): return reverse('sample:bookdetail', kwargs={'pk': self.pk})
こうすると、 views.py
でわざわざ if column == 'id':
なんてダサいif文をかまさなくて良くなる!と思ったが、最終形がイメージと違った・・・別に全部にリンクはいらないんだよな。というわけで、自分は「結論」に書いた実装とした。
参考までに全ソースはタグとして保存しておいた。
Release tag_get_absolute_url_sample · as-chapa/datatables · GitHub