te-touのブログ

音楽制作・車・プログラミング・旅行・その他考えてる事など、備忘録的なことも含めて個人的なページです。

ImportError: No module named django.core.wsgiエラーが解消しない。




どっぷりどハマり中です。
ここ2週間ほど(合間時間に)ローカル環境で作成したDjangoアプリをAWSのEC2(LINUX2)にデプロイ 作業を行っています。

f:id:te-tou:20200802003543p:plain
nginx エラー

こんな感じで。

ちなみに、環境は以下の通り。

  • Django3.0.2
  • PostgreSQL
  • Python3系
  • AWS EC2 LINUX2
  • gunicorn ←ここに問題あり
  • nginx

gunicornを起動すると以下のエラーがでます。

ImportError: No module named django.core.wsgi

gunicornが何かインポートできてなくて立ち上がりません。

設定ファイルを確認しても、特段問題無いように見えます。

WSGI config for app_name project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app_name.settings')

application = get_wsgi_application()

さっぱり意味不明です。
とりあえず、./manage.py runserver を打てば、サーバーが起動してIPアドレスで表示されているのでとりあえずは良い感じはしますが。
全くすっきりしないし、サーバー構築は難しい。
settings.pyを別ファイルにしてdev環境とprod環境に分割しているため、パスがうまく通ってないのかもと思いつつよくわかってない状態でどハマり中です。




ロゴデザインとTシャツ作成

 

最近、ひょんな事からTシャツ作成してました。

 

ついでにロゴ作成とかも。

f:id:te-tou:20200801170023j:plain

これらは個人的なものですが、waysknewって屋号として個人でなんかやるときに使っている名称です。

夏だしTシャツ欲しいな。と思ったときに巷で売っているものにあまり好みのものがなくてついでに作ってみました。

 

f:id:te-tou:20200801165947j:plain

これは、5年くらい前まで近所に住んでいた野良ネコ(地域ネコ?)です。

とても愛嬌があって、餌なんかあげなくても擦り寄ってくるネコだったのですがある日を境に見かけなくなってしまいました。もういい歳だったのかな?

昔、撮影の練習に撮った画像があったのでTシャツに印刷して額縁に飾っていつでも見られるようにしようと思い作成しました。

いつ見ても愛嬌があって可愛らしいです。

 

このような制作も面白いので、もう少し活動しようかと思ってます。

 

 

AWSのEC2(LINUX2)にPostgreSQLをいれる




走り書きの備忘です。
ローカル環境で作成したDjangoアプリをAWSのEC2(LINUX2)にデプロイ 作業を行っています。
その過程でPostgreSQLをインストールし、初期化→settings.pyのDatabaseを設定しマイグレートコマンドを打ったところ下記のようなエラーになりました。

django.db.utils.ProgrammingError: "WITH ORDINALITY"またはその近辺で構文エラー
LINE 6:                     FROM unnest(c.conkey) WITH ORDINALITY co...

ググった結果、どうやらPostgreSQLのバージョンが古いから的な記事に辿り着きました。
そのため、古いバージョンを消してPostgreSQL-11をインストールしています。
以下、その過程です。

古いバージョンのpostgreSQLを削除する。

すでにインストールされたものを探すコマンド
# yum list installed | grep postgresql
動作(running)していないか確認コマンド
# systemctl status postgresql-11.service
動いてたら止めるコマンド
# systemctl stop postgresql-11.service
削除コマンド
# yum remove postgresql*
PostgreSQLインストールコマンド

まずは、リポジトリを取り込むコマンド

# cd /usr/local/src
# curl -O https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# curl -O https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# rpm -Uvh pgdg-redhat-repo-latest.noarch.rpm

取り込んだリポジトリの確認コマンド

# yum list | grep postgresql11

取り込んだリストのインストールコマンド

# yum -y install postgresql11-server;
# yum -y install postgresql11-devel;
# yum -y install postgresql11-libs;
# yum -y install postgresql11;
# yum -y install postgresql11-llvmjit;
# yum -y install postgresql11-contrib;
# yum -y install llvm5.0;
# yum -y install llvm5.0-libs;
DBの初期化コマンド
/usr/pgsql-11/bin/postgresql-11-setup initdb
PostgreSQL-11起動コマンド
# sudo systemctl start postgresql-11
ステータス確認コマンド
# sudo systemctl status postgresql-11
終了コマンド
# sudo systemctl stop postgresql-11
PostgreSQLにアクセスするコマンド

まずはユーザー変更する必要あり。
ユーザー変更コマンド

$ sudo su postgres

コマンドライン起動(?)コマンド

$ psql
ロールの作成

root権限みたいなものを作るコマンド

postgres=# create role ユーザー名 with login password ‘パスワード';
文字コードをUTF-8にするコマンド
alter role ユーザー名 SET client_encoding TO 'utf8';
ドランザクションを独立させる(?)コマンド
ALTER ROLE ユーザー名 SET default_transaction_isolation TO 'read committed';
接続権限を与えるコマンド
GRANT ALL PRIVILEGES ON DATABASE データベース名 TO ユーザー名;

¥q(バックスラッシュ+q)して終わり。

Djangoの設定

settings.pyの編集

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'DB名',
        'USER': 'ユーザー名',
        'PASSWORD': 'パスワード',
    }
}

psycopg2というものをインストール
(pythonでpostgresqlを使うためのものらしい)

pip install psycopg2
PostgreSQLの認証方法を変更する

初期値はpeer認証になっているものをmd5というものに変更するらしい。

vimでPostgreSQLの設定ファイルを開く

vi /var/lib/pgsql/11/data/pg_hba.conf

peer を md5に変更する。

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     md5 ←ここ
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     md5 ←ここもついでに
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident

ここまでできたら、サーバー再起動。

sudo systemctl restart postgresql-11

これでようやくマイグレーションできました。

まとめ

いろんな事が起こりすぎて、吐きそう。




AWS SSH接続時の「port 22: Connection refused」問題




普段プログラマしてますが、大規模開発のなかにいるとサーバー周りのインフラ系に触ることがほぼありません。
なので、素人作業なので認識が大いに誤っているかもしれません。

事象

近頃AWSでサーバー構築をしていました。

インスタンスを立ち上げて、SSH接続して作業後切断します。
後日改めてSSH接続しようとすると、以下のような状態になりました。

$ ssh -i "something.pem" ec2-user@x.xx.xxx.172
ssh: connect to host x.xx.xxx.172 port 22: Connection refused

「port 22: Connection refused」
とりあえず、接続できないことだけは確かです。

対策

結論は「インバウンドルールの設定」でSSHのソースのIPを一度削除してから、もう一度「マイIP」を設定する。
それを行ったところ、

ssh -i "mjerapp.pem" ec2-user@x.xx.xxx.172
Last login: Sat Jul 18 19:34:23 2020 from xxx.xxx.xx.xxx

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/

つながりました。

詳細

ネットでいろいろ調べてみても、自身の知識不足からくる理解不足のため意味不明です。

なので、とりあえずport22がビジーになってるならそこをリフレッシュすれば良いかと思い確認しました。

セキュリティグループ → インバウンドルールの設定へ
f:id:te-tou:20200719111253p:plain

ポート22のソースを「マイIP」で設定したはずなのに、「カスタム」になってます。
こういうものなのかな?
f:id:te-tou:20200719111831p:plain

よくわからないけど、以下の手順を実行。

  1. IPアドレスを「×(ばってん)」で消します。
  2. ソースの「カスタム」をリストから選択して「マイIP」に変更。
  3. IPアドレスが設定されると思います。
  4. 「ルールを保存」

この手続きを行ったところ、上記のように再度SSH接続ができるようになりました。

まとめ

おそらく正規の方法では無い上に、場当たり的な対処法かと思います。

なんとなくやったら出来ちゃった的な。

この作業を行うことによってデータが損失する可能性が無いとは言い切れません。
根本的な対処法を確立することが急務です。
手順通りやっても大体うまく行きません。サーバー構築は難しい。


Django weasyprintでPDF出力。(日本語文字化け解消と用紙の設定とURLの引渡)




前回の続きです。
www.te-tou.tokyo

DjangoとweasyprintでPDF出力は無事に出来たものの、激しく文字化けしていました。
f:id:te-tou:20200614144752p:plain
ついでに用紙が縦になっていたり、セルの中の文字が予定外に折り返していたり、印刷したいURLをviews.pyに引き渡したりする方法がよく分かりませんでしたが一通り解決しました。

日本語文字化け解消

views.pyの中でCSSを指定して、フォントを設定してあげたら解消しました。

from .models import Person
from django.http import HttpResponse
from django.template.loader import render_to_string
# CSSもインポートしておく
from weasyprint import HTML, CSS
import tempfile

def generate_pdf(request):
    from django.template.loader import get_template
    html_template = get_template('testapp/scoringsheet_list.html') 

    html_str = html_template.render({

                },request)  

    pdf_file = HTML(request.GET.get('path')).write_pdf(

         stylesheets=[
# CSSを指定してフォントを設定することで、文字化け解消。
                 CSS(string='body { font-family: serif !important }'),
         ],
    )

    response = HttpResponse(pdf_file, content_type='application/pdf')
    response['Content-Disposition'] = 'filename="scoringsheet.pdf"'

    return response

出力結果

f:id:te-tou:20200621160301p:plain
Django weasyprint出力
文字化け解消しています。
ついでに後述する以下も解消されている状態です。

  • 印刷用紙を横向に設定
  • セル内の文字折り返ししない
  • 印刷したいページのURLをtemplateからviews.pyに引き渡し

細かいことは抜きにして、結構きれいにPDF出力出来たと思います。

用紙の設定

weasyprintでlandscapeです。
テンプレートファイル(HTML)にスタイル属性を追加します。

この中に用紙設定を書きます。

<style>
  @page {
      size: landscape;
      margin: 0.2in 0.1in 0.2in 0.1in;
</style>

landscapeが用紙横印刷ですね。
この辺りにA3とか書いておけば、印刷用紙サイズも変更できます。初期値はA4みたいです。
ついでに用紙の余白も設定しときます。

セル内の文字折り返し禁止

これもテンプレートファイル(HTML)にスタイル属性を設定します。

<style>
  @page {
      size: landscape;
      margin: 0.2in 0.1in 0.2in 0.1in;

# 文字折り返し禁止
  table tr span {
	    white-space: nowrap;
  }
</style>

white-space: nowrap;です。
「table tr span」のclass名は、table rawで横列(ヘッダ)部分を折り返し禁止にしています。

印刷したいページのURLをviews.pyに引き渡す。

PDF変換する流れは、

  1. 対象のページへアクセス
  2. 「PDF出力」ボタンを押下し、対象のページをPDF変換

という想定です。

そのため、まず始めに対象ページに「ボタン」をつけます。
template(HTML)

f:id:te-tou:20200621163111p:plain
Django PDF出力ボタン追加
こんな感じです。

次にそのボタンに自分のページのURLを引数として持たせます。
Django(python?)で今アクセスしているページのURLを取得する方法は、

{{ request.build_absolute_uri }}

と書くと、フルパスを取得してくれます。

ソースは下記の通り。
template(HTML)

<form action="/exportpdf/shinsa/" method="get" target="_blank">
    <input  type="hidden" name="path" value={{ request.build_absolute_uri }} >
    <button type="submit"> PDF出力 </button>
</form>

これでボタンを押下した際に、自分のページのURLを引数に持たせることができました。

次に、views.pyで受け取ります。
viewsで引数を受け取るために、

request.GET.get('name属性')

これでリクエストを受け取ります。

views.py

from .models import Person
from django.http import HttpResponse
from django.template.loader import render_to_string
from weasyprint import HTML, CSS
import tempfile

def generate_pdf(request):
    from django.template.loader import get_template
    html_template = get_template('testapp/scoringsheet_list.html') 

    html_str = html_template.render({
                },request)  
# request.GET.get('ボタンのnameを指定')
    pdf_file = HTML(request.GET.get('path')).write_pdf(

         stylesheets=[
                 CSS(string='body { font-family: serif !important }'),
         ],
    )
    response = HttpResponse(pdf_file, content_type='application/pdf')
    response['Content-Disposition'] = 'filename="scoringsheet.pdf"'

    return response

これでviews.pyにURLを直書きしなくても、印刷したいページのURLを受け渡せます。
templateファイルを指定しているので、なんでも良いわけでは無いと思います。が、同一のページでクエリで集計していたり抽出している結果を出力したい場合に有効だと思います。
はっきり言って仕組みを完全に理解していないので、そこそこ怪しいです。

まとめ

普段バッチプログラムとか作っていると、htmlを忘れるので当然のことがなかなかできなくなります。
特にCSS。

課題

CSSファイルをstaticで作ったのにファイルが読み込めません。的なエラーが出てしまいました。
なので今はtemplate(HTML)ファイルにスタイルシートを直書きしてます。
はっきり言ってダサいので、この辺りをきれいにしたいです。




www.youtube.com
www.facebook.com

Django weasyprintでPDF出力。(インストールと各種エラー対応と最終的に文字化け)




掲題の通り、Djangoで作成した画面をweasyprintを使ってPDF出力して印刷できるようにします。


まずは、weasyprintをインストールします。
しかし、いろんな物に依存関係があるようなので色々パッケージのインストールが必要です。
エラーを確認しながら進めます。なんか行き当たりばったりです。

環境
  • python : 3系
  • Django : version 3.0.2
  • SQLite
  • macOS Catalina

とりあえず、何かしらのアプリが作成されていることが前提です。
ついでにHomebrewもインストールされていることも前提です。

weasyprintインストール

Djangoのバーチャル環境にインストールするので、アプリをアクティベートしてからターミナルで以下のコマンドを打ちます。

pip install WeasyPrint

pipを最新化しろとメッセージが出たので、アップグレードします。

python3 -m pip install --upgrade pip
ソース

ざっくりソースを書きます。
views.py

from .models import Person
from django.http import HttpResponse
from django.template.loader import render_to_string
from weasyprint import HTML
import tempfile

def generate_pdf(request):
    from django.template.loader import get_template
# テンプレートを指定
    html_template = get_template('testapp/scoringsheet_list.html') 

    html_str = html_template.render({
#引数とかある場合は、ここに設定する。
      'Member': Member,
      'Scoringsheet': Scoringsheet,
                },request)  

    pdf_file = HTML('http://127.0.0.1:8000/scoringsheet?event=4').write_pdf(
# weasyprintではCSSを指定してあげないと参照してくれないようなので、必要なら指定する。
# 今回は特に使わないのでコメント
#        stylesheets=[
#           CSS('/static/css/something.css')
#        ],
    )

    response = HttpResponse(pdf_file, content_type='application/pdf')
# ダウンロードした時のファイル名称を設定。
    response['Content-Disposition'] = 'filename="scoringsheet.pdf"'

    return response

urls.py

urlpatterns = [
# weasyprint
    path('generate/pdf/', views.generate_pdf, name='generate_pdf'),
]
試しにPDF化実行すると、各種エラー発生

urlsに書いたアドレスにアクセス。
ローカルサーバーだと、以下のようなアドレスです。
http://127.0.0.1:8000/generate/pdf/

エラーが出ました。

django OSError: no library called "cairo" was found

cairoってのが無いようなので、サーバーを落としてHomebrewでインストールします。

brew install python3 cairo pango gdk-pixbuf libffi

再度サーバー起動。またエラー。

no library called "libcairo-2" was found
cannot load library 'libcairo.so': dlopen(libcairo.so, 2): image not found
cannot load library 'libcairo.2.dylib': dlopen(libcairo.2.dylib, 2): image not found
cannot load library 'libcairo-2.dll': dlopen(libcairo-2.dll, 2): image not found

なんか、色々ネットで対処法を探しているとpython3系ならpip3でインストールしないといけない。らしいので再度weasyprintをインストール。

pip3 install WeasyPrint

必要かどうか不明ですが、ここでもう一度cairoをインストール。

brew install cairo

また別のエラーが出ました。
もしかしたら、前にも出ていたかもしれませんがここで気がつきました。

Error: The following formula
  [#<Dependency: "python@3.8" []>, #<Options: []>]
cannot be installed as binary package and must be built from source.
Install the Command Line Tools:
  xcode-select --install

xcodeがバーチャル環境にちゃんと入っていないのかな?
よくわかりませんが、サーバーを落としてxcodeをインストール。

xcode-select --install

再度サーバー起動。またエラー。

    raise OSError(msg)
OSError: cannot load library 'pango-1.0': dlopen(pango-1.0, 2): image not found.  Additionally, ctypes.util.find_library() did not manage to locate a library called 'pango-1.0'

pangoってのが無いようなので、サーバー落としてpangoをインストール。

brew install pango

サーバー再起動。成功です。

PDF出力テスト

PDF出力するURLにアドレスにアクセスして、PDF出力テストします。
派手に文字化けしてしまいました。
(Djangoのテンプレート画面)

f:id:te-tou:20200614144612p:plain
Django テンプレート
(weasyprintでPDF出力結果)
f:id:te-tou:20200614144752p:plain
weasyprint PDF出力結果

日本語と数字が全滅です。
HTMLにはちゃんと文字コード指定をしてるのですが、関係ないようです。
ちなみに改ページしても、ヘッダはページごとについてきたので安心しました。

今後の課題

まずは上記の文字化けをなんとかしないといけません。
それが出来たら、A4で横向き(landscape)出力設定をしたいです。
現状調べたところ、よくわからないです。

まとめ

weasyprintはインストールが一つでは済まないのが難点です。
ソース自体はサンプルコードが結構落ちているので、とりあえずはなんとかなります。
しかし、細かい不具合についての対処法はあまり無いように感じました。この辺りは結構努力が必要そうです。
最後に、Djangoのテンプレート通りに出力はしてくれない様なのでCSSはweasyprint用にCSSはちゃんと指定した方が良いみたいです。

ついでに

(上記のソースでは関係ありませんが)ソースの書き方によっては、日本語があるとユニコードエラーが出るようなのでoutput.nameを以下のように変更。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 10: invalid start byte
output = open(output.name, 'r')
↓fix
output = open(output.name, 'rb')




www.facebook.com
www.youtube.com

ホンダビートPP1 オーバーフェンダー化(計画2・アーチ上げの費用とか)

 

 

続きです。

www.te-tou.tokyo

 

先日入手した汎用オバフェンをのこぎりで切り落として、ざっくりサイズを合わせてみました。

f:id:te-tou:20200607225044j:plain

ホンダビート  オーバーフェンダー

ちなみに取り付け前は、こんな感じ。

f:id:te-tou:20200607225159j:plain

ホンダビート  ノーマルフェンダー

やっぱり迫力が違います。

f:id:te-tou:20200607225421j:plain

ホンダビート  オーバーフェンダー

f:id:te-tou:20200607225454j:plain

ホンダビート  オーバーフェンダー

どんな感じで取り付けるかを考えつつ、フェンダーのアーチ上げをする場合の費用を近所の評判が良さそうな板金修理屋さんに聞きに行きました。

ずばり、リヤフェンダー2個で約10万円。

内訳を簡単に見ると、

  • アーチ上げのためのフェンダーカット
  • 切った部分にシール材を注入して処理
  • 汎用フェンダーの塗装
  • オバフェン取り付け などなど

内容としてはかなりきれいに仕上げてくれそうな感じでした。

しかし、10万かー。

あとは、構造変更とか諸々の手続き・ホイールとかワイドスペーサーとかの費用などなど。手間と時間はかかるけど、やっただけの満足感を得られるとは思います。

だがしかし、心は折れ始めました。

アーチ上げしないで取り付けられないかとは考えていますが、車高調はこれで車高一番高い位置っぽいからタイヤを外に出すと間違いなくフェンダーに当たっちゃいます。

タイヤを小さくするかなーとか考えつつ、なんかさっくり解決したいです。

 

 

www.youtube.com

www.facebook.com