python3.doc_66
R e i - D r e a m
for Laravel
TOP > Python3 > Django(色々DownLoad)
Guest
login

最終投稿日:2022年6月18日

Django(色々DownLoad)
テキストファイル
from django.views.generic import View
from django.http.response import HttpResponse
from io import StringIO
class IndexView(View):
    def get(self, request):
        output = StringIO()
        output.write('First line.\n')
        response = HttpResponse(output.getvalue(), content_type='text/plain')
        response["Content-Disposition"] = 'attachment; filename=text.txt'
        return response
            
JSON
from django.views.generic import View
from django.http import JsonResponse
class JsonView(View):
    def get(self, request):
        j = {'hoge':'ほげ','foo':['ふ~','ばぁ']}
        #辞書型を引数とする
        return JsonResponse(j)

表示例)
    ブラウザには以下の様に出力される
        {"hoge": "\u307b\u3052", "foo": ["\u3075\uff5e", "\u3070\u3041"]}

【メモ】
    JSON の内容を解析するには json ライブラリを使います。
    例)
        import json
        #文字列として受け取った場合
        j = '{"hoge": "\u307b\u3052", "foo": ["\u3075\uff5e", "\u3070\u3041"]}'
        #辞書型に変換できる
        data = json.loads(j)
        #表示結果 ⇒ {'hoge': 'ほげ', 'foo': ['ふ~', 'ばぁ']}
        print(data)
        #表示結果 ⇒ <class 'dict'>
        print(type(data))
        #辞書型を文字列の JSON 形式に変換できる
        s = json.dumps(data)
        #表示結果 ⇒ {"hoge": "\u307b\u3052", "foo": ["\u3075\uff5e", "\u3070\u3041"]}
        print(s)
        #表示結果 ⇒ <class 'str'>
        print(type(s))
            
XML
例1)
    from django.views.generic import View
    from django.shortcuts import render_to_response
    class XmlView(View):
        def get(self, request):
            p = {}
            p['status'] = 200
            p['msg'] = 'Success'
            #テンプレートの内容をレスポンスとして返却する
            return render_to_response(
                    #第1:テンプレート指定、第2:通信情報(任意)
                    'mysite/hoge.xml', {'data':p},
                    #ヘッダー
                    content_type='application/xhtml+xml'
                )

[mysite/hoge.xml]
    <?xml version="1.0" encoding="utf-8" ?>
    <info>
        <member>
            <array>
                <member_id>1</member_id>
                <member_name1>name1</member_name1>
            </array>
        </member>
    </info>

例2)
    from django.views.generic import View
    from django.http.response import HttpResponse
    class XmlView(View):
        def get(self, request):
            # 本来は動的に XML を作成する
            xml = '<?xml version="1.0" encoding="utf-8" ?>'
            xml += '<info><member><array><member_id>1</member_id>';
            xml += '<member_name1>name1</member_name1></array></member></info>';
            #テンプレートを使わずに送信
            return HttpResponse(
                    xml,
                    #ヘッダー
                    content_type='application/xhtml+xml'
                )
            
エクセルのアップロード ダウンロード [openpyxl]
ライブラリ openpyxl を使います。
※Anaconda3 があれば既に入っています
【注意】拡張子[xlsx/xlsm/xltx/xltm]のみ対応です
例)
    from django.shortcuts import render
    from django.http.response import HttpResponse
    from django.views.generic import View
    import os
    import openpyxl
    class XlsView(View):
        def get(self, request):
            #アップロード用の html を指定
            return render(request, 'mysite/xls.html', {})
        def post(self, request):
            #ファイルが指定されてない場合は何もしない
            if 'updata' not in request.FILES:
                return render(request, 'mysite/xls.html', {})
            else:
                obj = request.FILES['updata']
                #ファイルの拡張子を取得
                ext = obj.name[obj.name.find('.') + 1:]
                #使用可能な拡張子かチェック
                if ext not in ['xlsx','xlsm']:                                  
                    return render(request, 'mysite/xls.html', {})
                else:
                    dir = os.path.dirname(__file__)
                    #保存したい場合はここでフルパスを設定
                    file_path = os.path.join( dir, 'foo.' + ext )
                    #エクセル VBA の有無を設定
                    vba_flg = {'xlsx':False, 'xlsm':True}
                    #エクセルを開く
                    book = openpyxl.load_workbook(obj, keep_vba=vba_flg[ext])
                    #シートの 0番目を取得
                    sheet = book.worksheets[0]
                    #A5 セルに文字列代入
                    sheet['A5'] = 'ふが~'
    # -------------------------- サーバへ保存する場合 ------------------------------
                    book.save(file_path)
                    print('おわり~')
                    return render(request, 'mysite/xls.html', {})
    # -------------------------- ブラウザからダウンロードする場合 -------------------
                    new_file_name = 'foo' + '.' + ext
                    response = HttpResponse(content_type=
                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
                    response['Content-Disposition'] 
                        = "attachment; filename='" + new_file_name + "'"
                    book.save(response)
                    return response
    
    [mysite/xls.html]
        <html>
            <head>
                <title>アップロード</title>
            </head>
            <body>
                <form method='post' action='' enctype='multipart/form-data'>
                    <input type='file' name='updata'>
                    {% csrf_token %}
                    <input type='submit' value='送信'>
                </form>
            </body>
        </html>

【メモ】
    サンプルのライブラリは旧エクセルフォーマットには対応していません。
    一応旧フォーマットを操作するライブラリは以下があります。
        xlrd            エクセルを読み込むライブラリ
        xlwt            エクセルを書き込むライブラリ
    使い方例1)
        import xlrd
        book = xlrd.open_workbook('test_book.xlsx')
        sheet_1 = book.sheet_by_index(0)
        sheet_2 = book.sheet_by_name('hoge')
        col = sheet_1.ncols                         ※列数取得
        row = sheet_1.nrows                         ※行数取得

    使い方例2)
        import xlwt
        book = xlwt.Workbook()                      ※ブックを新規作成
        s = book.add_sheet('hoge')                  ※シートを新規作成
        s.write(0, 5, 'ほげ')                       ※E1に「ほげ」と入力
        book.save('foo.xls')                        ※保存
    
お分かりの通りこの2つのライブラリは別々なので双方のインスタンスに互換性はありません。
よって、xlrd は、読んだら読みっぱなし、xlwt は、新しいブックに新しいシートを作成して保存するのみです。

一応両ライブラリに互換性を持たすライブラリ xlutils もあります。
※Anaconda3 にはないのでインストールする
    pip install xlutils
        ※xlutils-2.0.0 をインストールした
以下のサンプルはアップロードした xls 形式のエクセルにシートを追加して値を書き込み保存する内容です。
例)
    import os
    import xlrd
    import xlwt
    from xlutils.copy import copy
    import openpyxl
    class XlsView(View):
        def get(self, request):
            return render(request, 'mysite/xls.html', {})
        def post(self, request):
            if 'updata' not in request.FILES:
                return render(request, 'mysite/xls.html', {})
            else:
                obj = request.FILES['updata']
                ext = obj.name[obj.name.find('.') + 1:]
                if ext not in ['xls']:
                    return render(request, 'mysite/xls.html', {})
                else:
                    dir = os.path.dirname(__file__)
                    file_path = os.path.join( dir, 'foo.' + ext )
                    save_path = os.path.join( dir, 'hoge.' + ext )
                    #新しく空のファイルを開き
                    destination = open(file_path, 'wb+')
                    for chunk in obj.chunks():
                        #アップロードしたエクセルを待避する
                        destination.write(chunk)
                    #で、改めてそのファイルをオープンする
                    rb = xlrd.open_workbook(file_path, formatting_info=True, on_demand=True)
                    #この処理で wb は、xlwt のインスタンスになっています。
                    wb = copy(rb)
                    s = wb.add_sheet('hoge')
                    s.write(5, 0, 'ほげ~')
                    wb.save(save_path)
                    print('おわり~')
                    return render(request, 'mysite/xls.html', {})
            
※なぜ一旦空のファイルを作りエクセルを待避してるかと言うと、request.FILES['updata'] の状態では、xlrd.open_workbook() でエクセルを読み取る事ができないからです。
ログインしてコメントを残そう!!


きっぷる
きっぷる