Pythonの時間がかかるプログラムをDjangoに入れる方法(インストール不要の開発環境で実行するサンプルプログラム付き)

この記事は約12分で読めます。
広告

ローカル環境で作ったPythonプログラムを公開したいとき
Djangoに組み込む方法があります。
この記事の目的はサーバーのタイムアウトを回避するための
サンプルプログラムの紹介ですが。
Django初心者でもPythonのプログラムを公開デプロイできるように
手順を書いてあります。

目的、手段がちょっと一般的ではないので余計な部分がありますが
Python単体のプログラム(今回sequencemo.py)の入れ方や
簡単なユーザーインターフェース(今回index.htmlなど)は参考になるかと思います。

手順のみなのでDjangoについて基礎から知りたい人は私の他の記事を参考にしてください。

何もインストールしないでも無料のWEBサービスPaizaCloudで
サンプルプログラム(これはHeroku上で動かしてる)が作れます。


この記事の続きです。

広告

サンプルプログラム

PaizaCloudで作ります。
PaizaCloud 使い方はこちらを参考にしてください。
その際Herokuへのデプロイを考えている場合
データベース:PostgreSQLを選択してください。
選択しても標準のSQLiteで動かせます。
この記事もSQLiteで動かしてからPostgresへ変更してます。

PaizaCloudの左にあるターミナルをクリック
以下のコードを入力

sequence_appという名前でプロジェクトの作成
django-admin startproject sequence_app 

sequence_appディレクトリへ移動
cd sequence_app

sq_appという名前でアプリ作成
python manage.py startapp sq_app
settings.py変更
sequence_app/sequence_app/settings.pyをダブルクリック

以下のように2か所変更
・ホストを全部許可する。
・アプリを追加

ALLOWED_HOSTS = [] → ALLOWED_HOSTS = ['*']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
  'sq_app.apps.SqAppConfig',      
#追加 sq_app/apps.pyにあるclass SqAppConfig(AppConfig):のクラス名を追加。'sq_app', だけでも動く
]

どこでもいいので下の1行追加
SESSION_ENGINE ="django.contrib.sessions.backends.signed_cookies"#クッキーで保存

今後ファイルを変更したら各Window左上の保存をクリック。
車両通行止めと同じマークが出ている場合は保存完了してます。

URL設定urls.py

URLと処理を紐づけします。
urls.pyはプロジェクト(sequence_app)とアプリ(sq_app)にそれぞれ必要です。
プロジェクト側のurls.pyは毎回同じです。
path(”,の’’はサーバーに割り当てられている大元のアドレスになります。
PaizaCloudの場合は後程プログラムを実行すればわかりますが
https://localhost-個人別の名前.paiza-user-free.cloud:8000/が大元となります。
なのでpath(”,include(“sq_app.urls”)),は上記アドレスにアクセスしたら
sq_app/urls.pyに行けという意味です。

プロジェクト(sequence_app)のurls.pyを変更

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include("sq_app.urls")),
]

アプリ(sq_app)のurls.pyは最初ないので
sq_appを右クリックして新規ファイル作成でurls.py作成
中身を以下にします。

from django.urls import path
from . import views

app_name    = "sq_app"
urlpatterns = [ 
    path('', views.SequenceView.as_view(), name="index"),
]

これもpath(’’なので大元のアドレスにアクセスしたら
views.pyのSequenceView.as_view()を実行しろという意味です。
as_view()は継承元のViewクラスのメソッドでviewオブジェクトを生成します。
Viewクラスを継承したクラスを実行する場合はこの形で共通のようです。
目次へ

データ処理 views.py

Viewクラス(get()、post()などHTTPメソッドに特化したビュークラス)を
継承してSequenceViewをつくります。
このViewクラスはgetとpostが来たときの処理を書けば済みます。
postでセッションのクリアと待ち時間dtimeの設定値を取得
getでアプリの処理本体sequence関数を呼び出す。
sequence関数はシーケンスNoにより実行される処理を分けている。
今回は全部time.sleepで待ち時間dtimeだけスリープしてます。
シーケンスNoを1増やして返す。

このgetがなぜ自動的に呼び出されるかは
前述してます。

views.py

from django.shortcuts import render

#クラスベースのビューを作るため
from django.views import View
#シーケンスのコードをインポート
import time
from . import sequencemo

#Viewを継承してGET文、POST文の関数を作る
class SequenceView(View):

    def get(self, request, *args, **kwargs):
        #nextボタンを自動的に押された時の処理
        if "next" in request.GET:

            dtime=request.session['dtime']
            sqn0=request.session['sequence_no']
            #処理時間実測タイマースタート
            start_time  = time.time()

            sqn    = sequencemo.sequence(dtime,sqn0)

            request.session['sequence_no']=sqn
            #処理時間実測タイマーストップ
            end_time    = int(time.time() - start_time)

            context = { "time"          : end_time,
                        "sequence_no"   : sqn,
                        }
            if sqn < 5:
                return render(request,"sq_app/results.html",context)
            else:
                return render(request,"sq_app/end.html",context)
        else:
            return render(request,"sq_app/index.html")

    def post(self, request, *args, **kwargs):
        #セッションクリア
        request.session.clear()
        #セッション&クッキー 削除
        request.session.flush()

        dtime=request.POST["dtime"]

        if dtime !="":
            request.session['sequence_no']=0
            request.session['dtime']=dtime

            return render(request,"sq_app/results.html")
        else:
            return render(request,"sq_app/index.html")

メイン処理

sq_appを右クリックして新規ファイル作成でsequencemo.py作成
中身を以下にします。
この例は全部time.sleepですが、時間のかかる処理を
分割してここに埋め込めばタイムアウトを回避することができます。

import time

def sequence(dtime,sqn0):
    if sqn0 == 0:
        time.sleep(int(dtime))
    elif sqn0 ==1 :
        time.sleep(int(dtime))
    elif sqn0 ==2 :
        time.sleep(int(dtime))
    elif sqn0 ==3 :
        time.sleep(int(dtime)) 
    elif sqn0 ==4 :
        time.sleep(int(dtime))  
    sqn=sqn0+1
    return sqn  

目次へ

表示 Template

sq_appを右クリック、新規ディレクトリでtemplatesディレクトリ作成
その下にもう1個sq_appディレクトリ作成
templates/sq_appを右クリックして新規ファイル作成でindex.html、results.html、end.html作成

index.html


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>シーケンスアプリ</title>

</head>
<body>
    <h1 class="title">シーケンスアプリ</h1>

	<form action="" method="POST">
	    {% csrf_token %}

 		<label>待ち時間: 
        	<input type="text" value=5 id=dtime" name="dtime">秒</label>
		<br>
        	<input type="submit" value="送信">

	</form> 

</body>
</html>

results.html
赤で書いたところが当記事の肝です。
results.htmlが表示されたと同時にJavaScriptでnextボタンを自動で押しています。
その結果Viewsのget処理が自動的に呼ばれる仕組みになります。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>シーケンスアプリ</title>

</head>
<body>

    <a href="./">ホーム</a>

	<form method="get" action="">
        {% csrf_token %}
        <p>時間間隔:{{ time }}秒</p>
        <p>
        <label>シーケンスNo<input type="text" name="next" value="{{ sequence_no }}"></label>
        </p>
    
        <p><input type="submit" id="button" value="Next"><label>ボタンは押さないでください。</label></p>
    </form>
    <script>
        document.getElementById('button').click();
    </script>


	</body>
</html>

end.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>シーケンスアプリ</title>

</head>
    <body>
        <h2>完了</h2>
        <a href="./">ホーム</a>

	</body>
</html>
python manage.py runserverでプログラムが実行できます。
PaizaCloudの左の8000をクリックすると表示します。

タイムアウトの確認

実行したら待ち時間を60秒以上にして実行してください。
エラーになります。
ちなみにHerokuでは30秒でエラーになります。
このタイムアウトの設定をPaizaCloudやHerokuで引き延ばす設定があるかはわかりません。
ちょっと調べた限りでは見つからなかったです。
目次へ

Herokuへのデプロイ

手順としてまずデータベースをSQLiteから
PostgreSQLへ変更(HerokuはPostgresSQLを使っているため)
PaizaCloudで動作確認してからHeroku用へ変更しています。

こちらの記事のデータベース接続設定(プログラム)からやってください。
その際PostgreSQLインストールとデータベース作成(ターミナルで作業)
「マイグレートして項目を作成 python manage.py migrate」までやればOKです。
python manage.py shellのデータベースへデータを書き込む部分は必要ありません。

PaizaCloudでデータベースをPostgresSQLへの変更は完了です。
動作確認して次にHerokuで動かすをやってください。
ここの「静的ファイル対応」は不要です。
静的ファイルとは画像やcss、jsを指します。
今回いずれも使用していないのでやる必要がありません。

デプロイ完了でデータベースに項目作って初期値を入れるという部分(run console以下)は不要です。
デプロイ完了したら何もせず「View」をクリックすればアプリが立ち上がります。
目次へ

MENTAやってます(ichige)




コメント

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