0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonスクリプト(帳票出力)をDjangoから実行

Posted at

はじめに

弊社が開発・運用・保守している+Auctionでは、pdf帳票生成・メール送信をpythonスクリプトから実行しています
基本的は定期実行なので、cronで運用していますが、スポット的にイレギュラーな場合があり、定期実行から外れることがあります
そういう場合を考慮して、Django Admin(Web)から、実行できるようにしました
帳票生成(メール送信)スクリプトをurlリンクから実行させる、というシンプルな思想です

概要

  1. ~/project/scriots/bin/create_join_invoice.pyを、~/project/app_name/views.pyにインポートし、CreateJoinInvoiceView()を設定する
  2. adminにurlリンクを設定し、CreateJoinInvoiceView()を実行する

帳票作成スクリプト

pdfrw、reportlabを使って、pdfを生成しています
他、Taxモデル、os、datetime、settings等importしています

scripts/bin/create_join_invoice.py
from pdfrw import PdfReader
from pdfrw.buildxobj import pagexobj
from pdfrw.toreportlab import makerl
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas

def main():
    # フォントの設定
    ttf_file = settings.FONT_PATH
    pdfmetrics.registerFont(TTFont('IPAexGothic', ttf_file))
    
    # ファイル生成
    cc = canvas.Canvas(file_path + '/' + file_name)
    
    # テンプレート読み込み
    page = PdfReader(settings.JOIN_FEE_TEMPLATE_INVOICE_PDF, decompress=False).pages
    
    # 1ページ目をオブジェクトに
    pp = pagexobj(page[0])
    cc.doForm(makerl(cc, pp))
    
    # 宛先
    cc.setFont('IPAexGothic', 16)
    target_x, target_y = 20 * mm, 255 * mm
    cc.drawString(target_x, target_y, custom_user.company_name) # defaultの描画(左寄せ)
    
    
    # 合計
    cc.setFont('IPAexGothic', 8)
    target_x, target_y = 145 * mm,  129 * mm
    cc.drawRightString(target_x, target_y, '¥ ' + str('{:,}'.format(join_fee.annual_fee + math.floor(sale_tax)))) 
    # 右よせの描画

    #
    # 実際はこの部分に、明細、請求元、消費税等があるが、長くなる
    # または、importしているので、複雑になることから割愛
    #
    
    cc.showPage()
    cc.save()

if __name__ == '__main__':
    main()
  1. IPAexGothicのインストール方法は、
    IPA Font ダウンロード | 一般社団法人 文字情報技術促進協議会等を参照ください

帳票生成スクリプトをviews.pyにimport

create_join_invoice.pyをapp_name/views.pyにimportし、webから実行できるようにします

app_name/views.py
from scripts.bin import create_join_invoice

class CreateJoinInvoiceView(SuperuserRequiredMixin, TemplateView) :
	def get(self, request, *args, **kwargs):
		context = {}
		context['back_link'] = '/admin/'+settings.ADMIN_PATH+'/app_name/script'
		context['title'] = '年会費(システム利用料)請求書生成スクリプト実行'
		context['detail'] = Script.objects.get(pk=self.kwargs['pk'])
		run_script = create_join_invoice.main() # create_join_invoice.py内のmain()を呼び出す
		context['script'] = run_script

		return render(request, 'app_name/invoice/invoice.html', context)

定期実行スクリプト用のmodel

スクリプトファイル名をDBに登録しておきます
DBに登録することで、DjangoのAdminから実行しやすくなります

models.py
class Script(BaseModel):
  title = models.CharField(verbose_name='タイトル', max_length=50, blank=False, null=False)
  detail = models.TextField(verbose_name='詳細・内容', blank=False, null=False)
  script_file_name = models.CharField(verbose_name='ファイル名', max_length=50, blank=False, null=False)
  run_time = models.CharField(verbose_name='実行日時', max_length=100, blank=False, null=False)
  url_link = models.CharField(verbose_name='実行スクリプトへのリンク', max_length=500, blank=True, null=True)
  • 共通Modelとして、BaseModelを必ず設定するようにしています
class BaseModel(models.Model):
  class Meta:
    abstract = True

  created = models.DateTimeField(verbose_name='生成日時', auto_now_add=True)
  modified = models.DateTimeField(verbose_name='更新日時', auto_now=True)
  deleted = models.DateTimeField(verbose_name='削除日時', blank=True, null=True)

url_linkに実行するファイル名を登録することで、後述するリンクを生成しやすくなります

Script ModelのAdmin画面

image.png

「スクリプト実行」をクリックすると、「CreateJoinInvoiceView()」から、「create_join_invoice.py」が実行され、帳票が生成される仕組みです

「スクリプト実行」リンクの生成

admin.py
list_display = ('run_time', 'title', 'script_file_name', 'detail', 'run_script_link')

.....

def run_script_link(self, obj):
    if obj.url_link:
       return mark_safe(
			'<a href="/xxxxxxxxxxxx/'+settings.ADMIN_PATH+'/' + str(obj.url_link) + '/'+str(obj.pk)+'">'+obj.title+'実行</a>'
			)
    else:
        return ''

run_script_link.short_description = 'スクリプト実行'

セキュリテイ対策として、urlに「settings.ADMIN_PATH(32桁の「ランダムな文字列)」を挟んでいます

app_nameアプリケーションのurl.pyより抜粋

url.py
path('{obj.url_link}/<int:pk>', CreateJoinInvoice.as_view(), name='create_join_invoice'),

終わりに

昔、CakePHPで同様な処理を行ったことがあり、Djangoでもいけんじゃね?と思い、このような処理にしてみました
帳票出力のサンプルはよく見かけますが、帳票出力+Webから実行の合わせ技はなかなか無いのではと思い、記事にしました
どなたかの参考になれば幸甚です

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?