2023年12月5日火曜日

Python: 現在のディレクトリ取得と変更

現在のディレクトリを取得

import os

cwd = os.getcwd()

print(cwd)  # /Users/demo-user/documents/mydir


ディレクトリを変更

os.chdir('/Library')

cwd = os.getcwd()

print(cwd)  # /Library



2023年10月24日火曜日

.htaccess リダイレクト設定 ‐ ファイル名に半角スペースやカッコがある場合

Apacheサーバーにあるファイルのリダイレクト設定です。

ファイル名に半角スペースや半角カッコがあっため 500 Internal Server Errorが発生してディレクトリにアクセスできなくなってしまいます。

.htaccess 最初の設定 *このままだと500エラーが発生

RewriteEngine On
Rewriterule ^abc xyz.pdf$ https://example.com/abcxyz/ [L, R=301]
Rewriterule ^abc(123)xyz.pdf$ https://example.com/abcxyz/ [L, R=301]


ファイル名をクオーテーションマーク " で囲い(^と$の外側に記述)、半角カッコはバックスラッシュ \ でエスケープが必要でした。

.htaccess 修正後

RewriteEngine On
Rewriterule "^abc xyz.pdf$" https://example.com/abcxyz/ [L, R=301]
Rewriterule "^abc\(123\)xyz.pdf$" https://example.com/abcxyz/ [L, R=301]

2023年9月26日火曜日

正規表現で改行を含んだワイルドカード指定

([\s\S\n]*?) または ([\s\S\n]⁺?)

*は0個以上の一致、⁺は1個以上の一致

  • \s: 空白文字を表す。[ \t\n\r\f]と同じ
  • \S: 非空白文字を表す。[ \t\n\r\f]以外の一文字。
  • \n: 改行文字を表す。

参考: VS Codeで複数行に渡って正規表現を利用する - Qiita
https://qiita.com/birdwatcher/items/dee34a11619b11e1fe81

2023年9月22日金曜日

django-CMSでのチェック方法

django-CMS (https://www.django-cms.org)

$ python manage.py cms check

を実行すると保存されておらずorphanedになったものが発見される場合がある。
以下を実行して削除する。

$ python manage.py cms list plugins

$ python manage.py cms delete-orphaned-plugins


2023年8月10日木曜日

Python クロージャ―で文字列を連続して連結

Pythonでクロージャ―を使って文字列を連続して連結する方法です。
def add_string():
    string = ''
    def add_string_inner(new_string):
        nonlocal string
        string += new_string
        return string
    return add_string_inner
messages = add_string()

print(messages(''))     # 空白
print(messages('abc'))  # abc
print(messages('123'))  # abc123
print(messages('xyz'))  # abc123xyz

2023年8月3日木曜日

Python テキストファイルを1行ずつ読み込み処理する readlines と readline メソッド

readlines() ... テキストファイル内容を一気に読み込み、1行ずつリストにします。ファイルサイズがよほど大きくなければ通常はこれを使います。

readline() ... テキストファイルを1行ずつ読み込みます。すべての行に対する処理は少し工夫が要ります。

以下、TEST.txt の内容が、

あいうえお[改行]
[改行]
かきくけこ[改行]
さしすせそ

というものとします。

2023年8月2日水曜日

Youtube サムネイル画像の取得

Youtube動画URL
https://www.youtube.com/watch?v=動画ID


120 × 90 [default]
http://img.youtube.com/vi/動画ID/default.jpg

120 × 90 [ 1 ]
http://img.youtube.com/vi/動画ID/1.jpg

120 × 90 [ 2 ]
http://img.youtube.com/vi/動画ID/2.jpg

120 × 90 [ 3 ]
http://img.youtube.com/vi/動画ID/3.jpg

320 × 180
http://img.youtube.com/vi/動画ID/mqdefault.jpg

480 × 360
http://img.youtube.com/vi/動画ID/hqdefault.jpg

640 × 480
http://img.youtube.com/vi/動画ID/sddefault.jpg

1280 × 720
http://img.youtube.com/vi/動画ID/maxresdefault.jpg


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:


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


2023年6月28日水曜日

Django: テンプレートでクエリパラメータを取得する

Djangoのテンプレートでクエリパラメータを表示したい場合です。

クエリ例1:https://example.com/?preview=ok&update=true&id=123

上記の例ようなクエリパラメータの場合、一つずつ取得するときは以下のようにします。

{{ request.GET.preview }} ⇒ ok
{{ request.GET.update }} ⇒ true
{{ request.GET.id }} ⇒ 123

一覧を表示したいときは以下のようにします。

{% for key, value in request.GET.items %}
    <p>{{ key }}: {{ value }}</p>
{% endfor %}

表示結果
preview: ok
update: false
id: 123

注意点としては、以下のようにパラメータに重複がある場合です。

クエリ例2:https://example.com/?preview=ok&update=true&id=123&id=xyz

この場合、{{ request.GET }} は

<QueryDict: {'preview': ['ok'], 'update': ['true'], 'id': ['123', 'xyz']}></QueryDict:>

のようなQueryDictなのですが、

{{ request.GET.id }} は リスト ['123', 'xyz'] になるわけではなく、後ろの'xyz'しか取得できません。

{{ request.GET.id }} ⇒ xyz


2023年6月23日金曜日

Django: テンプレートでuuidを文字列に変換

 DjangoでuserにUUIDフィールドを作ったので以下のようにテンプレートで条件判定しようとしたところ、同じUUID文字列のはずなのにどうしても一致しませんでした。

{% if "あるUUID文字列" == user.uuid %}

 ・・・・

{% endif %}


以下のように、uuidを文字列に変換しないといけませんでした。

{% if "あるUUID文字列" == user.uuid|stringformat:"s" %}

 ・・・・

{% endif %}


2023年6月15日木曜日

Ubuntuでfwupd-refresh.serviceがfailedになっている

Ubuntu: 20 or 22

以下のコマンドで起動中のサービス一覧を表示した。

$ systemctl list-units --type=service

その中で fwupd-refresh.service というものが failed になっていたのでその解決方法です。

次のファイルに User=root を追記します。
/lib/systemd/system/fwupd-refresh.service

[Unit]
Description=Refresh fwupd metadata and update motd
Documentation=man:fwupdmgr(1)
After=network.target

[Service]
Type=oneshot
User=root
CacheDirectory=fwupdmgr

・・・・以下略・・・・

サービスを再起動します。

$ systemctl daemon-reload; service fwupd-refresh restart; service fwupd-refresh status


参考: https://askubuntu.com/questions/1415928/cannot-start-fwupd-refresh-service

2023年5月15日月曜日

Django: shellでのモデルデータの取得方法

 $python manage.py shell

>>> from products.models import Product
>>> Product.objects.get(id=9)
<Product: レーザマシン>


>>> Product.objects.get(id=9).image
<FieldFile: products/product/9/photo1.jpg>


>>> Product.objects.get(id=9).image.name
'products/product/9/photo1.jpg'


>>> Product.objects.get(id=9).image.path
'/var/www/html/products/myproject/media/products/product/9/photo1.jpg'


参考
モデル (Model) - データアクセスの基礎 - Django 入門 - Python 入門
https://python.keicode.com/django/model-data-access-basics.php

2023年2月7日火曜日

Ubuntuのアップデートとアップグレード

以下の順に、updateとupgradeを実行します。

$ sudo apt-get update

$ sudo apt-get upgrade

※apt-get updateは、有効なインストール可能なパッケージの一覧を更新します。

※apt-get upgradeは、有効なパッケージ一覧を元にインストール済みパッケージの更新を行います。

参考 https://www.sejuku.net/blog/85434