【Django x jQuery】`Uncaught TypeError: $(...).DataTable is not a function`エラーの原因はライブラリの競合にあった

# 概要
- DjangoのテンプレートにjQueryの実装をしていたら`Uncaught TypeError: $(...).DataTable is not a function`のエラーメッセージが表示されてしまい、うまく動作しなくなってしまいました。
- 本記事ではこのエラーの原因と解決方法を紹介します。

# エラー概要
- DjangoでjQueryが実装されているHTMLを開くと、以下のメッセージがコンソールに表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/34fff1cd-d26e-3e98-abf9-11739e10131f.png)

```
common.js:74 Uncaught TypeError: $(...).DataTable is not a function
    at Object.success (common.js:74:42)
    at c (jquery-3.6.0.min.js:2:28327)
    at Object.fireWith [as resolveWith] (jquery-3.6.0.min.js:2:29072)
    at l (jquery-3.6.0.min.js:2:79901)
    at XMLHttpRequest.<anonymous> (jquery-3.6.0.min.js:2:82355)
```

- テンプレートではformを実装しているのですが、このエラーによってうまく`POST`されずに困ってしまいました。

# 原因の追求
- このエラーは、`DataTables`が正しく読み込まれていないことを示している...ということで、適切なバージョンのjQueryとDataTablesが読み込まれていない可能性があります。
- ただし、該当のDjangoテンプレートでは、しっかりjQueryとDataTablesのCDNリンクを使用していました。うーむ。

```sample.html
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script>
    $(document).ready(function() {
    # 省略
</script>

```

- 以下の参考記事にライブラリの読み込み順序が問題のこともある、とあったのですが、jQuery→DataTablesの順番になっているので問題なさそう。試しに逆でやってみるがやはり同じエラー。
    - 参考：[JavascriptのDataTablesが動かずにUncaught TypeError: $(...).dataTable is not a functionのエラーが出る原因](https://webcreator.webmeo.org/blog/750/)
- なんでだ～と思いもう少し調べてみると「jQueryの複数回読み込み」が問題になることもあるということを発見。とはいえ、同じテンプレートの中で複数読み込ませた記憶はないなぁ、、、
    - 参考：[TypeError: $(…).DataTable is not a function](https://www.gyrocode.com/articles/jquery-datatables-common-javascript-console-errors/#typeerror-datatable-is-not-a-function)

> jQuery DataTables library is missing.
> jQuery library is loaded after jQuery DataTables.
> Multiple versions of jQuery library is loaded.　←これのこと

- 複数バージョンかぁ...あれ、そういえばこのテンプレートは`base.html`というテンプレートファイルをオーバーライド（継承）して作っているのだった。もしやと思い見てみると...あった！（ここにいたのか！）

```base.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
```

- `sample.html`と`base.html`では異なるバージョンのjQueryライブラリが記載されているので、同ページで読み込むと競合してしまったのです。`sample.html`の方が後で読み込まれるので、`base.html`でjQueryバージョン3.1.0を読み込んだ後に、`sample.html`でjQueryバージョン3.6.0を読み込んでいたと考えられるでしょう。これにより、後のバージョン（3.6.0）のjQueryで提供されるDataTable関数が正しく動作しなかったのです。`base.html`の方は昔に記載したものだったのでアウトオブ眼中になっていました。

### 二つのURLの違い：公式ウェブサイトとCDN
- ちなみに、`https://ajax.googleapis.com/ajax/libs...`と`https://code.jquery.com...`どちらでもjQueryを利用することができますが、以下の違いがあります。
    - `https://ajax.googleapis.com/ajax/libs...`：Googleが提供している公開のコンテンツ配信ネットワーク（CDN）からライブラリの特定バージョンを直接リンクして利用する方法
    - `https://code.jquery.com...`：jQueryの公式ウェブサイトから提供されているjQueryの特定のバージョンファイルから直接ダウンロードして利用する方法
- 主な違いは、ファイルの提供元とリンクの方法、ということですね。どちらを使うべきかは、バージョン、パフォーマンス、キャッシュ、セキュリティなどの観点から判断することになります。CDNを使用することで、ファイルの配信速度やキャッシュの恩恵を受けることができるので、一般的にはCDNの方が使われている、といったところでしょうか。以下にもメリットとデメリットの記載あるのでご参考までに。
    - [【jQuery入門】CDNを読み込む方法と使い方まとめ！](https://www.sejuku.net/blog/65045)
    - [【jQuery】CDNの種類をまとめてみました](https://125naroom.com/web/3945)

# 解決方法
- `sample.html`の方のライブラリを削除したところ、エラーは表示されず解決しました。
- ライブラリの競合を回避してコーディングしていくべきということを実感したエラー対応でした。また、このエラーが出た場合は、以下の3つをまず疑っていきましょう。


> jQuery DataTables library is missing.
> jQuery library is loaded after jQuery DataTables.
> Multiple versions of jQuery library is loaded.