2023年7月27日木曜日

JavaScript: ブラウザ戻るボタンでページ表示されたときのイベント検知

フォームなどでブラウザの戻るボタンで戻ってきたときに、ブラウザのキャッシュにより以前の情報が表示されて困る場合があります。 検索すると、以下のようにすれば良しとあるのですが、どうもこの event.persisted が動作しません。(いつも false)
// 強制リロード
window.addEventListener('pageshow', function (event) {
  if (event.persisted) {
    // bfcache発動時の処理
    window.location.reload();
  }
});
その他、探したところ window.performance.navigation.type というものがあり、これを使うと意図通り動作しました。
window.addEventListener('pageshow', function(event) {
  let flg=window.performance.navigation.type;
  //flg=0が始めてきたとき、flg=1がリロードしたとき、flg=2がブラウザバックで戻ってきたとき
  if (flg == 2) {
      window.location.reload();
    }
});


参考: ブラウザバック を検知したい
https://teratail.com/questions/312782

2023年7月25日火曜日

Django: SQLiteが動作しない場合

Amazon Linux2 または CentOS7上でDjangoをインストールして、「$ python manage.py migrate」すると以下のようなエラーが出ました。

django.db.utils.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher.

SQLiteのバージョンが古いということで、アップグレードしても同じようなエラーが出ます。

こちらのサイト https://stackoverflow.com/questions/66380006/django-deterministic-true-requires-sqlite-3-8-3-or-higher-upon-running-python によれば、以下のようにすればよいとのことでした。

まず、pysqlite3 と pysqlite3-binary をインストールします。(仮想環境です)

(venv)$ pip install pysqlite3

(venv)$ pip install pysqlite3-binary

そして、以下のbase.pyの一部を書き換えます。

venv/python3.9/site-packages/django/db/backends/sqlite3/base.py

# from sqlite3 import dbapi2 as Database # annotation

 ↓ 以下のようにします。

from pysqlite3 import dbapi2 as Database # import pysqlite3

再度 migrateし、ウェブサーバーを再起動したところ動作するようになりました。


2023年7月21日金曜日

JavaScript: Cookie値取得関数を作ったときつまずいた3点

問題点1: Cookieをsplit()で配列にするとCookie名で値の取得ができなくなる。

解決方法: Cookieを取得して、";" でsplitではなく、"; " (半角スペース付)でsplitする。
let cookie_arry = document.cookie.split('; ');

参考【JavaScript】Cookieをsplit()で配列にするとCookie名で値の取得ができなくなるhttps://into-the-program.com/javascript-cant-get-value-cookie-name-array/


問題点2: forEachの仕様上、以下のように forEach内でreturnができない。
function getCookieValue(cookie_name) {
  let cookie_arry = document.cookie.split('; ');
cookie_arry.forEach(function(value) {
var content = value.split('='); if (content[0] == cookie_name){ return content[1]; //ここで終了せず、配列最後まで繰り返してしまう。 } }) }

解決方法: ふつうにforを使う。
function getCookieValue(cookie_name) {
  let cookie_arry = document.cookie.split('; ');
for (let value of cookie_arry) {
content = value.split('='); if (content[0] == cookie_name){ return content[1]; } } }

JavaScriptのArray.forEachをbreak、continue、returnさせたい
https://www.deep-rain.com/programming/javascript/778


問題点3: なぜか値を取得できないCookieが一部ある。
解決方法: HttpOnly属性のCookieはJavaScriptで取得できないので無理。

特にログインが必要なサイトで、ログイン後に生成される sessionid等のCookieが undefinedになってしまう。
getCookieValue('sessionid'); //⇒ undefined
これらのCookieをブラウザのデベロッパーツールで確認すると、HttpOnlyが有効になっている。
HttpOnly属性とは、クライアント側でJavaScriptなどからアクセスできないようにするもので、クロスサイトスクリプティング(XSS)攻撃などでCookieの内容を読み取られるのを阻止することができる。そのため、セッションIDなどはHttpOnlyが有効になっている場合が多い。

2023年7月20日木曜日

Tabulatorで他のフィールドを参照して書き換える

Tabulatorで他のフィールド(セル)を参照して書き換える方法です。

formatterに getValue(), getData() を使用して関数を定義します。

cell.getValue() でフィールド自身の値を取得できます。
cell.getData() でフィールドを含む行のデータを取得できます。
cell.getData().[他のフィールド名] で他のフィールドの値を取得できます。


    let table = new Tabulator('#example-table', {
      ajaxURL: './item.json',
      layout:"fitColumns", //fit columns to width of table (optional)
      columns: [
        {
          title: '名称',
          field: 'name',
          formatter: function(cell){
            let name = cell.getValue();
            let pdf_url = cell.getData().pdf_url;
            if (pdf_url) {
              return `<a href="${pdf_url}" target="_blank">${name}</a>`;
            } else {
              return name;
            }
          }
        },
        { title: 'PDF', field: 'pdf_url', visible: false },
・・・・・ ・・・・・


2023年7月19日水曜日

Wiki.js 画像フォルダを削除する方法

Wiki.jsで画像・ファイルをアップロードするときフォルダ作成ができますが、ブラウザ上で削除ができません。(2023年7月現在)
Wiki.jsをDockerでインストールしている場合のフォルダ削除方法メモです。


Dockerのdbイメージ(PostgleSQL)に入ります。

$ docker exec -it db /bin/bash


User: wiki、Database:wikiでPostgreにログインします。

root@db:/# psql -h 127.0.0.1 -p 5432 -U wiki -d wiki


以下のようにselectでテーブル一覧を表示します。


wiki=# select * from public."assetFolders";

 id |     name      |     slug      | parentId
----+---------------+---------------+----------
  1 | folder-user   | folder-user   |
  2 | folder-common | folder-common |
  3 | folder-admin  | folder-admin  |
(3 rows)


削除したいフォルダのid(以下の例では3)を指定してdeleteで削除します。

root@db:/# delete from public."assetFolders" where id=3;


2023年7月14日金曜日

Python クラスの定義で (object) は要るのか要らないのか?

Pythonでのクラスの定義を見ると古い情報では以下のように (object) が付いていることが多い。

class NewStyleClass(object):


Python2では、何も継承しないクラスを記述する場合に以下のように記述する。

class MyClass: または class MyClass():

そして、objectクラスを継承したクラスというものがあり、以下のように記述する。

class MyClass(object):

Python2では、この2つは区別される。


Python3では、この3つはすべてobjectクラスを継承したクラスとなるため、同じものになる。そのため、Python3では以下のように簡潔に記述すればよい。

class MyClass:


参考: 新スタイルのクラスと旧スタイルのクラス