te-touのブログ

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

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';
DBを作るコマンド
create database DB名 encoding 'UTF8' owner ユーザー名;
接続権限を与えるコマンド
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

ホンダビートPP1 オーバーフェンダー化(計画)

 

かねてから、ホンダビート の車幅の狭さがかっこ悪いと常々思ってました。

しかし、車幅を変更するということは構造変更やらなんやら結構一大事です。

 

とまあ、長年色々考えていましたが汎用オーバーフェンダー買いました。

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

汎用オーバーフェンダー

たしか、片側8cm。

 

実際の取り付けとかは今は考えず、とりあえず位置合わせしてみます。

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

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

でかいな。

長い部分は切り落とすとして、やっぱりこうした方がカッコいい。

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

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

なかなかの迫力です。

しかし、でかい。

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

ホンダビート

真横から見ると、元のフェンダーが見えてしまってます。

タイヤもどうせやるならツライチにしたいので、深リムホイールに変えるかワイドスペーサーをかませるか対応すると思うのでフェンダーのアーチ上げが必要です。

流石にアーチ上げは専門の板金屋さんに頼まないとですが、どれくらい予算がかかるか不明です。

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

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

これくらいワイドな方がカッコ良いです。

さてさて、どうするか。

 

汎用オバフェン自体は7千円しないくらいでしたが、実際の取り付けとかタイヤ周りをいじるとなると結構予算がかかりそうなので悩みます。

 

 

www.youtube.com

www.facebook.com

Django win10にanacondaインストールしてDjangoの開発環境をつくる。

 

タイトルがカタカナと横文字が多くてバカっぽいですが、win10でanacondaからのDjango開発環境作成の走り書きメモです。

anacondaインストール

まずは、anacondaインストール。

www.anaconda.com

このリンクの下部に環境(macとかwinとかbitとか)ごとのダウンローダがあるので、PCにダウンロードしてからexeを開くとインストール開始。

途中選択画面で迷ったら、ググればなんとかなります。

pathを通す

コマンドプロンプトを使って、どこのディレクトリにいても呼び出せるようにパスを通しておきます。

 

まず、win10で環境変数を開きます。

win10はコントロールパネルの開き方からしてわかりづらいのですが、画面左下の「ここに入力して検索」に「環境変数」と入力すると候補を出してくれます。

f:id:te-tou:20200523161352p:plain

win10 環境変数の開き方

下図のように「環境変数」を押下し、pathを選択して「編集」を押下。

f:id:te-tou:20200523162840p:plain

win10にanacondaの環境変数追加

下記のパスを新規に追加します。

  • C:\Users\(ユーザー名)\Anaconda3
  • C:\Users\(ユーザー名)\Anaconda3\Scripts
  • C:\Users\(ユーザー名)\Anaconda3\Library\bin
コマンドプロンプトで確認

pythonのバージョン情報を確認してみて、ちゃんと表示されたら良しとします。

  • python -V

f:id:te-tou:20200523165223p:plain

python -V

ついでにPower shellで使えるようにするには、PsCondaEnvが必要らしいです。

下記コマンドでインストールできます。

  • conda install -n root -c pscondaenvs pscondaenvs
仮想環境作成

仮想環境がなんたるかは、とりあえず開発環境をいれる「箱」を作るイメージだとおもっています。

たくさん作れるし、いらないのは消せるし。

ちゃんと箱を分けておけば、箱の中が混ざり合わなくて変なことも起こらないし程度に認識してます。

 

なので、ざっくり「箱」の名前を決めます。⇒とりあえす「test」にしときます。

コマンドプロンプトで下記のコマンドを打って仮想環境を作成します。

  • conda create -n test ⇒「test」の部分は任意の名称をいれます。

途中で「proceed?」と聞かれるので、「y」で返します。

仮想環境確認

下記のコマンドで環境情報を確認できます。

  • conda info -e

f:id:te-tou:20200523174904p:plain

conda info -e

「test」という環境が作成されました。

環境のアクティベート

下記のコマンドで仮想環境をアクティベートします。

  • activate test ⇒「test」の個所は作成した仮想環境名

f:id:te-tou:20200523174935p:plain

仮想環境をactivate

activate コマンドを打つと、(test)というのがプロンプトの先頭に表示されます。

 

ここでもう一度、仮想環境確認コマンド。

  • conda info -e

f:id:te-tou:20200523233043p:plain

conda info -e after activation

アクティベートした「test」環境に*(アスタリスク)マークがつきました。

 

ちなみにアクティベートをやめるときは、以下のコマンドで。

  • deactivate

先頭の(test)が消えます。

 仮想環境にDjangoをインストール

仮想環境の中にDjango開発ができる材料をインストールします。

  • conda install django

f:id:te-tou:20200523233731p:plain

conda install django

「proceed」は「y」でenter。

そうすると、目盛りが動いてさいごに「done」が表示されてインストールが終わります。

 

インストールを確認するために、コマンド打ちます。

  • conda list

f:id:te-tou:20200523234413p:plain

conda list after django install

リストが表示され、Djangoがインストールされてることがわかりました。

 

ここまでで、win10にanacondaインストールしてDjangoの開発環境をつくりました。

まとめ

windowsでの環境構築はめんどくさい。

 

 

www.youtube.com

www.facebook.com