Djangoでcsvをアップロード、pandasで処理しダウンロードするまで
はじめに
pythonでのデータ処理、機械学習を勉強中の初心者です。
今回は作成した回帰モデルを用い、アップロードされたテストファイルを読み込み、Notebookで行うようなpandasでのデータ処理を行い、結果のcsvファイルをweb上でダウンロードするところまでの機能を持つアプリを作成しました。
ネット上にはDjangoでpandasを使う方法があまり見当たらず、いろいろと調べて試しながら完全に自己流で作ったので至らぬ点もあるかとは思いますがご容赦ください。
環境と前提
Windows10
django 3.1.7
python 3.9.2
プロジェクト作成
$ django-admin startproject myproject
$ cd myproject
$ python manage.py startapp app
ディレクトリ構造
myproject/
app/
__pycache__/
migrations/
static/
files/ (new)
train_x.csv
train_y.csv
__init__.py
admin.py
apps.py
forms.py (new)
functions.py (new)
models.py
tests.py
views.py
myproject/
__pycache__/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
static/
templates/
index.html
db.sqlite3
manage.py
フォームの作成
forms.pyを作成します。
from django import forms
class UploadForm(forms.Form):
testfile = forms.FileField()
これをindex.htmlで使うだけでよく見るファイルを選択するフォームが作れます。とても便利ですね。
<div class="form-group">
<form method="POST" class="form" enctype="multipart/form-data">
{% csrf_token %}
<div class="file-upload-wrapper">
<p>テストファイルを選択<br \>
{{ form.testfile }}
</p>
</div>
最後にmyproject/urls.pyの設定
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name='index'), (追加)
]
お決まりのsettings.pyの細かい設定
(省略)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app', (追加)
]
(省略)
TEMPLATES = [
{
(省略)
'DIRS': [BASE_DIR, 'templates'],
(省略)
},
]
これでおそらく$ python manage.py runserverでローカルホストにアクセスするとファイル選択のフォームができているはずです。
アップロードされたファイルの処理
今回はfunctions.pyにファイル処理の関数を書き、それをviews.pyで使っていきます。
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from app.forms import UploadForm
from app.functions import process_file,to_csv
import csv,io
import pandas as pd
# Create your views here.
def index(request):
if request.method == 'POST':
upload = UploadForm(request.POST, request.FILES)
if upload.is_valid():
data = pd.read_csv(io.StringIO(request.FILES['testfile'].read().decode('utf-8')), delimiter=',')
df = process_file(data)
response = to_csv(df)
return response
else:
upload = UploadForm()
return render(request, "index.html", {'form':upload})
def index(request):から三行くらいまではformからPOSTで受け取るときの定型のようなものらしいです。
data = pd.read_csv(io.StringIO(request.FILES['testfile'].read().decode('utf-8')), delimiter=',')ここが一番苦労しました。
単にpd.read_csvだけでは読み取れず、いろいろ試しまくった結果これでいけました。
pandasでデータを処理していくprocess_file()と、データフレームをcsvファイルにしてダウンロードさせるto_csv()関数をfunctions.pyで作り、views.pyで使用する。
データの処理、ダウンロード
import pandas as pd
import numpy as np
import sklearn,csv,re,os
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from django.http import HttpResponse
from myproject.settings import BASE_DIR
def process_file(data):
#train_x = pd.read_csv("app/static/files/train_x.csv")
#train_y = pd.read_csv("app/static/files/train_y.csv")
train_x = pd.read_csv(os.path.join(BASE_DIR, 'app/static/files/train_x_modified.csv'))
train_y = pd.read_csv(os.path.join(BASE_DIR, 'app/static/files/train_y_modified.csv'))
test = data
#お好きなようにデータ処理
df_result = #最後にcsvに変換したいデータフレームとして返す
return df_result
def to_csv(df):
response = HttpResponse(content_type='text/csv; charset=UTF-8')
response['Content-Disposition'] = 'attachment; filename="result.csv"'
df.to_csv(path_or_buf = response, encoding = 'utf-8-sig', index=False)
return response
データ処理に必要なモジュールをそれぞれインポートしておきます。
process_file()
まず、トレーニングデータをmyproject/app/static/files/から読み込んでいます。
ローカルではpd.read_csv("app/static/files/~")でも大丈夫だったのですが、サーバーにデプロイして環境が変わったときに読み込めなくなったのでBASE_DIR/app/static/files/~となるように設定しました。
(ちなみにBASE_DIRはsettings.pyで定義されており、デフォルトではmanage.pyの存在するディレクトリだそうです。つまりこの例ではmyproject/になります。)
その後は関数process_file()内でNotebookで行っているような処理を自由に書くことができて、最後にデータフレーム型で返してあげます。
to_csv()
process_file()のレスポンスとして帰ってきたデータフレームをcsvに変換し、ダウンロードします。
最初の二行は定型です。HttpResponseとして"result.csv"という名前のcsvファイルを返します。attachmentをつけることで、フォーム内のボタンをクリックすると自動的にダウンロードが開始されるようになります。
ここでも時間を使ったのがdata.to_csv(path_or_buf = response, encoding = 'utf-8-sig', index=False)の部分で、path_or_buf = responseとすることでデータフレームをcsvに変換しダウンロードまでつなげることができるようになりました。
本当の最後に、index.htmlのform内にボタンをつけてあげて完成です。
<div class="form-group">
<form method="POST" class="form" enctype="multipart/form-data">
{% csrf_token %}
<div class="file-upload-wrapper">
<p>テストファイルを選択<br \>
{{ form.testfile }}
</p>
</div>
<p>テストファイルをアップロードし、予測結果の'result.csv'ファイルをダウンロードする</p>
<button type="submit" class="save btn btn-outline-primary">Upload and Download</button>
</form>
</div>
補足
今回は時間がなかったためアップロードされたファイルのバリデーションチェックは省略しました。
Djangoでpandasを使用する方法を調べていると、django-pandasというライブラリをインストールして使うという説明しか見当たらなかったのですが、python標準モジュールのpandasでもこのようにしてできるようです。
Author And Source
この問題について(Djangoでcsvをアップロード、pandasで処理しダウンロードするまで), 我々は、より多くの情報をここで見つけました https://qiita.com/vossibop/items/258a147f185da5c480d4著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .