Djangoで多対多のカラムがあるときにdjango-import-exportを使う方法

新サイトに移転しました。

sbskn.com

おことわり

この記事はdjango-import-exportを多対多に対応させる訳ではなく、DB構造の方で対応しようという内容です。

現状

Djangoでモデルを作成し、DBにCSVデータを流し込むぞ!というときに、django-import-exportが非常に便利だが、多対多リレーションのカラムがあると、素直にdjango-import-exportに頼ることができない。

ネットを調べてみると、対応する方法はヒットしたものの、正直よくわからない・・・

問題点

なぜ今回、多対多の時に困るかというと、Djangoでは多対多リレーションが存在するときに、自動的に中間テーブルを作成してしまう。

通常、Djangoの管理サイトでDBに手動でデータを追加する場合は多対多カラムもポチポチ押せば良いのだが、はて、CSVで流し込みたいときはどうすればいい?となる。

解決策

中間テーブルを自分で定義して、その中間テーブルに合わせたCSVデータを作成し、django-import-exportで流し込む。

中間テーブルについては以下の記事が非常にわかりやすいので参考までに。
qiita.com

uWSGIをサービスとして動かせない時の対処法

新サイトに移転しました。

sbskn.com

現状

uWSGIをサービスとして動かしたかったので、サービスユニットファイルを作成し、いざ起動!・・・できなかった。
以下エラー内容。

~略~
Active: failed (Result: protocol)
~略~
systemd[1]: Stopped uWSGI
systemd[1]: <サービス名>.service: Start request repeated too quickly.
systemd[1]: <サービス名>.service: Failed with result 'protocol'.
systemd[1]: Failed to start uWSGI.
~略~

原因

デーモン化されているものをサービスとして起動しようとしていたことが問題。

解決策

uWSGIの構成ファイル(uwsgi.ini等の名前で作成しているはず)のdaemonize設定を削除する。私の環境では以下のように記述していたので、これを削除。

daemonize = %(base)/manage.log  //デーモン化についての記述

再度サービスを起動(サービスユニットファイルは作成済みという前提です)

//uWSGIをサービスとして起動
> sudo systemctl start <サービス名>

//サービスのステータス
> sudo systemctl status <サービス名>
~略~
Active: active (running)
~略~

//サービスの自動起動設定(蛇足)
sudo systemctl enable <サービス名>

snap版Nextcloudでoccコマンドが使えない時の対処法(nextcloud.occ: command not found)

新サイトに移転しました。

sbskn.com

状況

snapでインストールしたNextcloudのもろもろの設定を行いたく、管理用のCLIであるoccを以下のように使おうとしたところ、「コマンドが見つからないよ」と怒られた。

> sudo nextcloud.occ
sudo: nextcloud.occ: command not found

対処法

以下のように絶対パスで指定することにより解決する。

> sudo /snap/bin/nextcloud.occ

追記

恐らくこのエラーが出る場合は他のNextcloudの設定もコマンドが通らないと思うので、パスを確認してみよう。

> cd /snap/bin/
> ls
nextcloud.disable-https  nextcloud.export  nextcloud.manual-install  nextcloud.mysqldump
nextcloud.enable-https   nextcloud.import  nextcloud.mysql-client    nextcloud.occ

これらのコマンドを使うときは「/snap/bin/<上記の使いたいコマンド>」と指定すればよいことが分かる。

グローバル変数の使用を回避する書き方。(クラスを使う)

グローバル変数を使わずに関数から変数をいじりたい

以下、色々省略したコードで説明。あくまで期待する動作なので、書き方としてはこれは間違い。

i = 0 #元の値

def hoge_func():
    i = 100 #値を変更

print(i)
#実行結果
>100 #関数内での変更が反映!

関数外で宣言した変数を何かしらの関数で変更して、その変更を関数の外でも適用できるようにしたい。
上の例だと元々変数iの値は0だが、hoge_funcによって100に書き換えられ、関数の外でprintしても値が100のままになっている。これを正しく書き直す。

条件

グローバル変数を使わない。

方針

クラスを使います。
1. 新しくクラスを作り、クラス内で変数を定義する(メンバ変数という)。
2. メンバ変数を外部から操作する。

やってみよう

例によって色々省略したコードで説明。

class teigi:
    i = 0

def hoge_func():
    teigi.i = 100

print(teigi.i)
#実行結果
>100 #目的達成!

1~2行目:クラスteigiでメンバ変数iを定義し、0で初期化しています。

3~4行目:関数でメンバ変数をいじります。メンバ変数を指定するために<クラス名>.<変数名>と書きます。上の例では、teigi.iとなります。

5行目:メンバ変数を表示します。関数hoge_funcによって書き換えられているので100が出力されます。

これで以上です。実装の際は上のプログラムに関数呼び出しを加えれば完成です。

vagrantがupできない(Timed out while waiting for the machine to boot.する)時の対処法

新サイトに移転しました。

sbskn.com


「何もしていないのに壊れました!!」

昨日まで動いていたはずのvagrant upが突如として動かなくなることは意外とよくあるらしい。色々な原因があるらしいが、私の場合は結構単純だったのでご紹介。

結論から書くと

Hyper-VWindowsサンドボックスを無効化したら解決。

これで解決する可能性があるのはWindows10 Pro以上のエディションの場合のみ(HomeエディションはそもそもHyper-Vなどがないので)。

(後日、Hyper-Vを無効化しているのにvagrant upできない症状が再発したので、その時の対処法を記事の最後に追記。)

環境

Windows10 Pro(21H2)上のVirtualBox6.1.32上のvagrant

起こったトラブル

vagrant upしようとすると以下のようにSSH接続の段階でタイムアウトしてしまう。

>vagrant up
==> default: ...
~省略~
    default: SSH auth method: private key(以下エラー)
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.

対処法

上手くいっていた時と今回のvagrant upで何が違うかな?と考えてみると、そういえばこの間にHyper-VWindowsサンドボックスを有効化してた!ということで早速無効化。
タスクバーの検索ボックスから「Windowsの機能の有効化または無効化」で検索>Hyper-VWindows サンドボックスのチェックを外す(両方無効化しないと解決しなかった)

チェックを外したらPCを再起動。これでvagrant upできるようになっていた。

ちなみにvagrantタイムアウト問題を調べてみると公開鍵の問題やVMのバージョンの問題など色々出てくるので、あくまで一つの解決策ということで。

追記

Windowsの機能の有効化または無効化」でHyper-VWindowsサンドボックス無効化したにも関わらず改善しない場合は「hypervisorlaunchtype」が「Auto」になっている可能性がある。これを「off」にする。

Powe Shellを管理者で起動して以下のコマンドを実行。

bcdedit

ブートローダーのステータス一覧の「hypervisorlaunchtype」を確認。「Auto」の場合は以下のコマンドで「off」にする。

bcdedit /set hypervisorlaunchtype off

終わったら再起動。

【Tkinter】バインドされた関数の呼び出し時は引数にselfを与える TypeError: click() takes 0 positional arguments but 1 was givenの対処法

新サイトに移転しました。

sbskn.com

やろうとしたこと

PythonTkinterでエントリー*1に入力した文字をプログラムに読み込ませるときに、エンターを押して実行できるようにしたかった。

*1 エントリー
Tkinterにおける文字の入力欄のこと

問題のコード(該当箇所のみ)

def click():
     #ボタンを押したときの処理

entry.bind('<Return>', click)

一番下の行でエンターキーの入力を押したのを感知し、感知したら関数click()を実行する、というコードです。

出たエラー

TypeError: click() takes 0 positional arguments but 1 was given

click()関数は0個の引数をとるはずだけど1個の引数が与えられたよ、というエラーです

解決策

関数click()の引数にselfを与えてあげる。

def click(self):
     #ボタンを押したときの処理

entry.bind('<Return>', click)


以上、関数中でバインドされた関数を呼び出すときはselfをつける、というお話でした。

Ubuntu20.04でのMySQLのインストールから初期設定まで

新サイトに移転しました。

sbskn.com

環境

$ lsb_release -a
//省略
Description:   20.04 LTS
//省略

MySQLのインストール

現時点でバージョンは8.0.27でした。

$ sudo apt update
$ sudo apt install mysql-server

初期設定

以下のコマンドを実行します。

$ sudo mysql_secure_installation

設定はこちらのサイトで詳しく解説されています。
symfoware.blog.fc2.com
7つの設定項目が順繰り出てきます。簡潔に意訳したものが以下の通り。(yesならyを、noならnを入力します。)
私が行った設定も記載していますが、各自適切に設定してください。

・パスワードを設定するか?[y or n]
これはy
・パスワードの強度はどうするか?[0~2(2が最も強い)]
これは0(1にすると特殊文字を設定する必要があり、勉強用の環境としては不便)
・rootパスワードの設定[前項に従った任意の文字列]
何かしら設定
アノニマスユーザーを削除するか?[y or n]
これはy
・外部からrootでログインすることを拒否するか?[y or n]
これはy
・デフォルトのデータベース「テスト」を削除するか?[y or n]
これはy
・テーブルをリロードするか?[y or n]
これはy

設定は以上です。

MySQLに接続&ステータス確認

MySQLに接続。

$ sudo mysql -u root -p
Enter Password:[設定したパスワード]

接続後、ステータスを確認したい時は次のコマンド。

mysql> status

MySQLの停止

$ sudo service mysql stop

起動、再起動は"stop"の部分をそれぞれstartもしくはrestartに読みかえて下さい。

注意点

この記事で紹介した設定は、私の個人的な勉強かつクローズドな環境に向けたものなので、セキュリティを考慮していないことに注意してください。