pythonのFlaskを使ってみた備忘録

テーマはPythonのFlask pythonの話

その1:url_for を使うとアドレスに「index.cgi」が入ってしまう

ローカルでやっていた時には問題ないですが、レンタルサーバーにアップして、url_forを使ってurlを発生させると、なぜか「XXX.com/index.cgi/hoge」のようにルートとエンドポイントのアドレスの間に「index.cgi」が入ってしまいます。

根本的な原因は分からずですが、どうやらCGIとして実行するのがいたずらしているようです。

逆にアドレスに「XXX.com/hoge」と打ち込めば、普通にアクセスできる状態です。

そこで、スマートではないですが、url_for で発生したアドレスは、replaceメソッドで「index.cgi」を消すことで対応することにしました。

スマートじゃないなあ。。。。

htmlのテンプレートにfor_urlがある場合の例です。
「 .replace(‘/index.cgi/’, ‘/’) 」で無理やり消しています。

<form action="{{url_for('hoge').replace('/index.cgi/', '/')}}" >
          <input type="submit" value="実行">
</form>        

すべてのurl_forにこれをしないといけないので、スマートじゃないですが、今後は常にローカルで作るときから入れておくようにしようと思います。

もし「index.cgi」が入らないような方法が見つかっても、replaceで対象が見つからずに置換されないだけなので、つけておくデメリットはなさそうなので、すべてに入れておこうと思います。

その2:FlaskFormからTextAreaFieldデータをjinja2に渡す。

フォームに初期値を表示させる場合で、TextAreaFieldの場合は注意が必要です。

普通のStringFieldの場合

<p>{{ form.name.label }}{{form.name(value=user.name)}}</p>

と「value」を使って初期値として表示させることができます。

TextAreaFieldの場合

<p>{{ form.message.label }}{{form.message(value=users.message)}}</p>

TextAreaFieldは、valueを使ったこの書き方では表示されません。

{% set fe = form.message.process_data(user.message) %}
<p>{{ form.message.label }}{{form.message()}}</p>

と1行目を書かないとダメです。

理由は、StringFieldやIntegerFieldと違って、TextAreaFieldがvalue属性をもっていないからです。
そのため、valueでは初期値をフォームに渡せません。

python — WTForms-textareaフィールドに事前入力する方法は?のサイトが参考になります。

その3:ローカルからレンタルサーバーへのアップの備忘

久々にやってみたらエラーが出たので備忘のメモです。

簡単な手順

  • app.pyを置くところに「.htaccess」ファイルを置く
  • index.cgiを置いてこれを起点にする。
    • 1行目にpythonのパスを入れる。必要なライブラリをインストールした仮想環境のものを指定する。(これはpythonの着火点のindex.cgiだけでOK)
    • index.cgiにapp.pyのappをインポートして起動させるようにする。
  • templatesやstaticsのフォルダとファイルをアップする。

動かないときに確認すること

  • Windowsで作ったファイルをアップすると上手く読み込めずに実行時にエラーになることがあるような気がする。
    改行コードをLFにしていてもエラーになることがあるような気がする。
    レンタルサーバのファイル管理ツールからテキストファイルを作成して内容をコピペしたら動いたことがある。
  • index.cgiのパーミッションは確認したほうがよい。この場合は、「Permission denied」などのエラーがでるはず。
  • pyファイルが沢山あるときはインポートのパスを確認する。下位フォルダに入れているファイル同士でimportしているとエラーになることがある模様。
    「from .ファイル名 import ~」とするか、「from . import ~」とする。
    ローカルで動かすときに問題なくてもサーバに上げるとエラーになることもある。
    ローカルでも自身のファイルから起動する場合とコマンドプロンプトでflask runを使うときでもimportの挙動が違うことがある気がする。
  • FlaskをAPIとして使っていてリクエストをJavaScriptから送ってるときはリクエスト先のURLを変更する必要がある。
  • render_templateでのファイル名の間違いやBlueprintを使った場合はパスの記載もれ。templates‐app名のフォルダ構成したときは”app名/ファイル名.html”になる。
  • staticフォルダのCSSファイルやJSファイルもファイル名の間違いにも注意。
  • 不要なprint(XXX)が入っていると文字コードの関係でエラーになることもある。PDFの読み込みをやったところ、print(XXX)が入ってるとエラーになるがこの行をコメントアウトすればエラーが解消されたことがある。

その4:Blueprintを使って拡張する

Blueprintを使って拡張するときの備忘です。

Blueprintを追加するファイルに追加するものをインポートして「register_blueprint」で登録する。

# 追加するフォルダからapp.pyファイルをインポートする
from add_dir import add_app as new_app

# blueプリントを追加する。
app.register_blueprint(new_app.app_name, url_prefix="/prefix")

追加するモジュールでは、Brueprintの追加インポート、Brueprintインスタンスの作成、エンドポイント名の変更、templateのパスを変更する。
templateやstaticsはファイル名がかぶらないならアプリ名フォルダの作成は不要、templateフォルダにアプリ名のフォルダ追加したときはアプリ名フォルダから記載が必要になる。

# Blueprintを追加でimport
from flask import Blueprint

#app = Flask(__name__) とBrueprintに書き換える
app_name= Blueprint("app_name", __name__,
                    template_folder="templates",
                    static_folder="static") 

# @のエンドポイント名をappからアプリ名に変える
# render_templateのファイル指定はtemplateフォルダ以下のpath
@app_name.route("/")
def index():
    return render_tempolate("app_name/index.htmel")

htmlファイルのCSSとJSファイルのパスを修正する。

<link href="{{ url_for('app_name.static', filename='add_app_style.css') }}" rel="stylesheet" type="text/css" media="all">

 <script src="{{ url_for('app_name.static', filename='pdfsimple_modifynd.js') }}"></script>

その5:レンタルサーバでは表示されるがローカルで表示されない

素人なので手順を踏まずにやるのが悪いというのは分かっています。普通はローカルで開発サーバを使って開発して、それをレンタルサーバに上げます。

素人なのでめんどくさがってちょっとした修正ならレンタルサーバのファイルをいじってしまうのでこんなことが起こります。

こんな感じで、本当はstaticフォルダのなかにimagesフォルダを作るのが本来ですが、staticsとは別にimageというフォルダを作って画像ファイルを格納しました。

myapp/
    |- app.py
    |- static
    |    |- style.css
    |- templates/
    |-   |- index.html
    |- image/
         |- sample.png

htmlではこのようにapp.pyからのパスで画像を指定します。

これでレンタルサーバでは画像は表示されました。

<img src='image/sample.png'>

しかし、このプロジェクト一式をダウンロードしてローカルのflask run で走らせたら、画像は表示されませんでした、ブラウザで404のnot found のエラーとなります。

この問題は、flaskの開発サーバでは、静的ファイルは指定したフォルダのものしか返されません。デフォルトでは”static”のフォルダです。

そのため、imageフォルダのファイルをflaskのローカルでの開発サーバでは静的ファイルとして返されないため画像が表示されない結果となります。

一方で、レンタルサーバの場合は、サーバの機能で公開フォルダのパスであれば静的ファイルとして取り扱われるので、staticフォルダ以外のフォルダでもパスが正しければ画像が表示されます。

コメント

タイトルとURLをコピーしました