Skip to content

Commit

Permalink
feat: Add django-datatables-view-100-over, remember-wovn-ignore and v…
Browse files Browse the repository at this point in the history
…ue-empty-string-truthy (#10)
  • Loading branch information
bicstone authored Feb 25, 2024
1 parent 9285cba commit 4448dbf
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 0 deletions.
114 changes: 114 additions & 0 deletions public/django-datatables-view-100-over.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: django_datatables_viewで1ページ100件超えが表示できない不具合の対処法
tags:
- Python
- Django
- プログラミング
- DataTables
- django-datatables-view
private: false
updated_at: "2024-02-25T16:28:20+09:00"
id: 70e5fbaed37799484e0a
organization_url_name: null
slide: false
ignorePublish: false
---

Djangoでdatatablesのサーバー連携を使用できるdjango_datatables_viewで、1ページあたり100件を超えるレコードがすべて表示できない不具合の対処法を紹介します。とてもわかりにくい不具合になっており、目視だと気が付かない可能性があります。

※ これは2021/03/28に個人ブログで公開した記事を移植したものです。

## django_datatables_view について

django_datatables_viewとは、datatablesのサーバー連携を使用できるDjangoのクラスベースビューです。
datatablesとは絞り込み・ソートなど多機能なテーブルをかんたんに実装できるjQueryプラグインです。

Djangoの管理画面よりもカスタマイズ豊富な上に、ほとんどプログラムを書くことなく、(デザイン, フロントエンド, バックエンドも)何も考えずにデータベース内容を一覧に表示できます。

![django-datatables-viewを使用しているテーブルのスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/b9f9deba-cd7e-6fad-ef2d-86d9c3c26390.png)

今回のユースケースでは、次のプログラムをお借りしました。ありがとうございます。

https://github.com/okoppe8/django-datatables-view-sample

## 1 ページあたり 100 件超えにするとレコード数がおかしい

datatablesの `lengthMenu` を変更すると、1ページあたりの表示件数を柔軟に変更できます。

10件でも、1件でも、2^53-1件でも設定できます。

![datatables で件数が変更できる部分のスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/25b47c4c-a350-9707-e374-64e5b4096a23.png)

https://datatables.net/reference/option/lengthMenu

ある案件で、最大「500件」の選択ができるように設定していました。500件にすると次のようになります。

![datatables で表示件数500件にしたスクリーンショット。しかし、1件目から100件目しか表示されていない。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/00d7526d-35e9-27c5-e709-203e28366cb5.png)

一見すると、正しく表示できていそうに見えますが、皆さん、このスクショにある「不具合」を1点見つけてくださいませ。

いくら北海道がデカいとはいえ、地方自治体が500もあるわけがないのです。(ちなみに179あるらしいです)

試しに次のページに行ってみましょう。

![datatables の表示件数500件にして2ページ目に行ったスクリーンショット。501件目から表示される。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/021c0e06-6053-d40e-18f2-e2a0f59d51e5.png)

群馬県に突入しています。つまり、「1 ~ 500件表示」となっていながら、500件のレコードが表示できていないのです。実際には100件しか表示されていません。

その案件ではデフォルトは100件にしており、テストもそれで通っていたので目視でしか確認しておらず発見できていませんでした。気づきにくい重大な不具合を生んでしまったのです。

## django_datatables_view の返却レコード数上限

django_datatables_viewには返却レコード数上限の設定( `max_display_length` )があります。README.mdには次の記述があります。

> set max limit of records returned, this is used to protect our site if someone tries to attack our site
> and make it return huge amount of data max_display_length = 500
https://pypi.org/project/django-datatables-view/

リクエスト自体は単純なGETのため、やろうと思えば大量のデータを取得する攻撃ができてしまう意図から設定されている設定です。こちらのデフォルト値は `100` になっています。

## 返却レコード数上限を変更する

正常に動作させるためには返却レコード数上限を変更する必要があります。`lengthMenu` の最大値を設定しましょう。

```py
from django_datatables_view.base_datatable_view import BaseDatatableView

class ExampleList(BaseDatatableView):
model = MyModel
columns = ['id', 'name', 'dateAt', 'updatedAt']
max_display_length = 500
```

再度実行してみましょう。

![表示件数を500件にしたdatatablesのスクリーンショット。1-500件目が正しく表示されている。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/04f4d670-500c-45f9-6ccf-408296c61659.png)

無事群馬県までの500件が表示されるようになりました。

## 基本設定のクラス化

複数のページで使用している場合、設定漏れがあると不具合の原因となるので、基本設定は基底クラス化してしまいましょう。次のように作ります。

```py
from django_datatables_view.base_datatable_view import BaseDatatableView

class ExtendDatatableView(BaseDatatableView):
# フロントdatatablesのlengthMenu最大値と揃えること
max_display_length = 500
```

```py
from app.library.extend_datatable_view import ExtendDatatableView

class ExampleList(ExtendDatatableView):
model = MyModel
columns = ['id', 'name', 'dateAt', 'updatedAt']
```

## まとめ(反省)

- ライブラリのREADMEはちゃんと読もう
- 目視で不具合に気がつけるようにテストデータは分かりやすくしよう
- テストは条件変更した場合の挙動も確認しよう
67 changes: 67 additions & 0 deletions public/remember-wovn-ignore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: wovn-ignoreを入れ忘れない方法
tags:
- CSS
- プログラミング
- Web
- wovn
- wovn-ignore
private: false
updated_at: "2024-02-25T16:28:20+09:00"
id: 197350d50e79ac00bb8e
organization_url_name: null
slide: false
ignorePublish: false
---

Webサイトの多言語化・翻訳対応を一任できるサービスWOVN.ioにおいて、個人情報や動的な数字がWOVNに送信されないように翻訳抽出対象外にするwovn-ignoreを設定し忘れない方法を紹介します。

※ これは2021/03/29に個人ブログで公開した記事を移植したものです。

## WOVN.io について

Webサイトの多言語化・翻訳対応を丸投げできるSaaSです。資産は日本語のまま、JSタグを追加するだけでGoogle翻訳のように翻訳をしてくれます。Google翻訳とは異なり、辞書を登録したり、人力で翻訳をしてもらうこともできます。

ちなみに読み方は「ウォーブン」だそうです。私の周りでは「ウーヴン」や、「オーブン」など様々な呼び方がされていました。初期はみんなビビって「ダブリューオーヴィエヌ」と呼んでいました。ASUSみたいですね?

https://wovn.io/ja/

Webエンジニアとしては、システム上での多言語対応はほとんどしなくて良くなるのでかなり開発が楽になります。

しかし、サービスの特性上、ユーザーがサイトを開いたときに、表示されている文言がすべてWOVNに送信され自動登録されてしまいます。個人情報や、動的な数値などがすべて登録されてしまい、セキュリティ面や費用面でも問題があります。

## wovn-ignore 属性について

そこで、抽出対象外を設定する `wovn-ignore` 属性というものが用意されています。

https://wovn-support.zendesk.com/hc/ja/articles/360007899791

HTML属性に `wovn-ignore` を追加するだけでそのタグ内はすべて除外されます。

```html
会員名:<span wovn-ignore>おおいし</span>様
```

ちなみに似た設定に「コンテンツ除外ルール設定」や「ライブ編集」があるのですが、WOVNにログインしないと対象かわからなかったり、誤って設定を変更してしまったり、HTMLの構造変更で対象が認識されないなどの危険があります。確実な運用ができないので避けていました。

## wovn-ignore を入れ忘れる

WOVNを入れる予算が確保できるほどの大規模サイトであれば、wovn-ignore属性を設定するべき箇所は無数にあるはずです。

そんなプロジェクトで何人もの開発者が携わると絶対に発生するのが属性の「入れ忘れ」、「スコープ漏れ」、そして「スペルミス」です。しかも、入れ忘れていないか確認する方法がソースコードを確認するしかないという苦行です。

そこで、絶対に誰が開発しても「入れ忘れ」、「スコープ漏れ」と「スペルミス」を防止できる方法を発明したので、皆さんに伝授します。

```css
*[wovn-ignore] {
background: fuchsia;
}
```

https://codesandbox.io/embed/wovn-ignore-ucer9y?theme=light&view=preview

なんということでしょう!wovn-ignore属性のただのテキストがたった3行のCSSでドギツい赤紫色に生まれ変わったではありませんか!

これなら絶対に間違えません。しかも、サイズなどに変更がまったくないのでデザインの影響もありません。 私が携わっていた案件では、あまりにもミスが多かったので開発環境のみこのCSSが設定されています。さすがに…という場合はブラウザのユーザースタイルシートや開発者ツールで設定するという方法もあります。

サイトのデザインと同化せず存在感を放つ色を選定してみてください。
66 changes: 66 additions & 0 deletions public/vue-empty-string-truthy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Vue で空文字が Prop で渡ってきてバグってしまった話
tags:
- JavaScript
- プログラミング
- Vue.js
- vue2
private: false
updated_at: "2024-02-25T16:28:20+09:00"
id: 0bca7652fa65c5f5e85d
organization_url_name: null
slide: false
ignorePublish: false
---

数年前に作られていたvue 2 (TypeScriptなし) のプロダクトで空文字がPropで渡ってきてバグってしまった話と、注意点を備忘録として残します。

※ これは2022/12/05に個人ブログで公開した記事を移植したものです。

## 背景

数年前に作られていたvue 2 (TypeScriptなし) のプロダクトで次のようなコンポーネントがありました。

```js
export default {
props: {
sample: Boolean,
default: false,
},
};
```

このコンポーネントはこのように呼び出されています。

```vue
<template>
<Sample :sample="sample2" />
</template>
```

このsample2、実は文字列が入っていました!

設計者の意図としては、JSの暗黙的な型変換と同様に空文字列であれば `false` 、 1文字以上であれば `true` という実装にしたかったのだと考えられます。

## 空文字列 `""``true` !?

ある日、 sample2に空文字列 `""` が入ってきました。しかし、 Sampleが `true` の場合の挙動をします。

なんと、 空文字 `""` が入ってきたときにコンポーネント内で `true` に変換されていたのです。

空文字 `""` はJavaScriptの真偽判定においてFalsyになるのでしばらく原因を理解するのに時間かかりました。

https://developer.mozilla.org/ja/docs/Glossary/Falsy

原因は、 `v-bind` において、 falsyな値は `null`, `undefined`, `false` だけという仕様があるためです。

https://v2.vuejs.org/v2/guide/migration.html#Truthiness-Falsiness-with-v-bind-changed

## なぜ

HTML Attributeと同じ挙動になるように揃えたみたいです。個人的にはReact (JSX) と同じ挙動なのでわかりやすく感じます。 v-ifなどは引き続きJavaScriptの真偽判定と同様の挙動をするようです。

## まとめ

- そもそもbooleanなpropに文字列を渡さないようにしよう
- このようなプログラムを書かれないように規約を設けるという意味でもTypeScriptは必須ですね

0 comments on commit 4448dbf

Please sign in to comment.