ギャバンITサービス
お菓子の家が作れるシステムエンジニアです

djangoをdockerコンテナで利用(19) - ログアウト画面で真っ白

定期更新してたらdjango5があることに気づいた。 来年に5.2のLTS出るんやな。 予定として6.0のことも書いてある。 2026年のことまで書いてあるのは気ぃ早いなぁ。 4.2.7を使ってたのを、勇気を出して5.0.2に変えてみた。 バージョン上げてみる pip3で普通にやってみる。 おお、他にも色々上がっとるやん。 テストしてだいたいOKやったけど 2015年頃からデータベースに帳簿とか画像とかpdfが入ってて、読み書きはできた。 帳簿も2020年のを見比べると金額あってたから、データベース関連の処理とか集計の処理は大丈夫っぽい。 見た目一緒やから別ページのリンク画像やけど、円グラフも表示できてた。 LTSやないから期待してへんかったけど、django5でも行けるんとちゃうか。 と思ってたら、最後のログアウトしたところで画面真っ白。 なんかヤな予感。 前にdjango3をdjango4にあげたときにどっかのページ表示でこんなんあったような、なかったような・・・。 だいたい真っ白のときにはサーバからまともなhtmlが戻ってきてへんのな。 調べてみた 検索してみると、logoutviewでgetが非推奨になったらしい。5.0になったらなくなってまうってよ。 Djangoの認証システムを使用する | Django ドキュメント | Django docs.djangoproject.com 脆弱性対応とかなんやろけど、どないしたらええんやろか。 ログアウトできんと困るやん。 対処方法探す 同じ様なことをやってる人がいた。 getの代わりにpostメソッド使えばええみたいやけど、getメソッド許可するの? 侍テラコヤ(SAMURAI TERAKOYA) - 日本最安級のサブスク型オンラインITスクール terakoya.sejuku.net そういえば自分のログアウト処理の箇所はこう書いてた。 1 <a href="https://nafslinux.intra.gavann-it.com:30443/gvisWebApp/logout/" >イントラwebDjangoログアウト</a> ほなこう書いてpostメソッド指定してみよ。 1 2 3 4 <form action="{% url 'gvisWebApp:logout' %}" method="post"> {% csrf_token %} <input class="darkmode-ignore" type="submit" value="ログアウト"> </form> そやけど、これだけやったらアカンかった。 まだ真っ白画面になった。 ...

djangoをdockerコンテナで利用(18) - djangoのインボイス対応

インボイスってのが来月から始まる。 消費税をゴソっと徴収されてまう苦しいルール。 受け取った消費税を、支払った消費税で相殺して払えばええらしいんやけど、この計算けっこう手間がかかる。 売上が1000万円もあるわけないから、時限ルールの2割納税を適用させてもらうけど、計算処理は作っとかなアカン。 djangoで作った帳簿の処理を改造することにした。 目標設定 経費を入力するテーブルに、金額のフィールドがあるのを、8%と10%の消費税を保持させて、月単位集計と年単位集計にその合計を表示させる。 最近受け取ったレシートとかみると、もう適格請求書発行番号を書いてあるものがあった。 なるほど、こうやるんやって横目で見ながら自分のexcel請求書も書式変更した。 結果 だいたいこんなことをやった。 2023autumn pycファイルをgit対象から除外 python3.10を3.11、requirements.txt内モジュールのバージョンアップ カレントデータベース表示の追加 ローカル環境をテスト用mariadbに変えてインボイス対応の実施 インボイス対応 ここが今回の主な作業。 migration(0011_gviskeihi_gvismstkamoku_gvismstkeihishubetsu.py)にうまく追加されないのでpycファイルを手動で削除してから追記しdockerコンテナをビルドしなおし 経費テーブル(GVIS_Keihi)に消費税8%(tax8kng)と消費税10%(tax8kng)の格納項目を追加 モデル(GvisKeihi.py)に経費テーブルの追加列を追記 経費明細のテンプレート(gvis_50x_Keihixxx(Detail/Delete/Update).html)に追記 帳簿のテンプレート(gvis_600_ChoboKensaku.html)に追記 view(gvis_keihi_views.py/gvis_chobo_views.py)に追記 共通処理(common.py)の年間売上経費取得処理(gv_Func_uriageKeihi)を年間売上経費&消費税取得処理に内容変更 共通処理(common.py)に年間受け取り消費税合計取得処理(gv_Func_ukeTaxGokei)と年間支払い消費税取得処理(gv_Func_shihaTaxGokei)を追加 アプリケーションの更新 djangoはpythonのwebフレームワークで、MVT(model・view・template)ってのを組み合わせて作る。 modelはデータベース、templateはhtml、viewは実処理を意味してる。 データ構造を変更するときは、modelを変えてマイグレーションを動かして更新させるんやけど、このやり方が自分にはどうしても気に食わない。 データベース上の列の型とかは自分でコントロールしたいから、マイグレーション使わずに手動で更新した。 データベースのテーブルを更新 もう10年ぐらい前からデータベースを維持してて、最初はphpでwebアプリを作ってた。その頃は navicatのmysql接続版 を使ってた。 5〜6年前やったと思うんやけど、mysqlをやめてmariadbに乗り換えて、去年からphpをやめてdjangoに切り替えた。 今は a5sql を使わせてもらってる。 作者さんありがとう。 昔はa5sqlでテーブルの列追加ってやったことなかったけど、最近見たらめっちゃ楽にできることに気づいた。 テスト用スキーマを開いて、テーブルの設計更新を選ぶとこんな画面が出て、列追加ができる。 金額の列の後ろに消費税8%と10%の列を足してから左上にある「DDL生成」ボタンを押す。ここで右端にある「引き継ぐ値」は何も入れないでおくと、「デフォルト式」の値が設定されるみたい。 すると、新しいsql窓が開いてコメントつきでsqlが作られてビックリ。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 -------------------------------------------------------------------------------- -- `nariDB_Django`.`GVIS_keihi` のレイアウト変更 -- 注意!!:テーブルに依存するオブジェクト(ビューなど)が削除される場合があります。それらのオブジェクトは復元されません。 -- 2023/09/13 nari -------------------------------------------------------------------------------- -- 新テーブルの作成 create table `nariDB_Django`.`$$GVIS_keihi` ( id int(11) auto_increment not null comment 'id' , `workPeriod` datetime comment '業務期間-開始日' , `workShubetsu` char(4) comment '経費種別' , `workPriority` int(10) comment '経費No-優先順位' , `Keihi_date` datetime comment '経費日付' , `Kamoku` varchar(24) comment '科目' , `Tehai` varchar(1000) comment '手配方法・名称・機種' , `Kng` decimal(12,4) default '0.0000' comment '金額' , `Tax8Kng` decimal(12,4) default '0.0000' comment '消費税8%' , `Tax10Kng` decimal(12,4) default '0.0000' comment '消費税10%' , `Biko` varchar(100) comment '備考' , ins_date datetime comment 'データ作成日' , ins_user varchar(100) comment 'データ作成ユーザ' , upd_date datetime comment 'データ更新日' , upd_user varchar(100) comment 'データ更新ユーザ' , primary key (id) ) comment='' engine InnoDB row_format DYNAMIC auto_increment 10554 collate utf8mb3_general_ci / -- 新テーブルへデータ投入 insert into `nariDB_Django`.`$$GVIS_keihi`(id, `workPeriod`, `workShubetsu`, `workPriority`, `Keihi_date`, `Kamoku`, `Tehai`, `Kng`, `Biko`, ins_date, ins_user, upd_date, upd_user) select org.id, org.`workPeriod`, org.`workShubetsu`, org.`workPriority`, org.`Keihi_date`, org.`Kamoku`, org.`Tehai`, org.`Kng`, org.`Biko`, org.ins_date, org.ins_user, org.upd_date, org.upd_user from `nariDB_Django`.`GVIS_keihi` org / -- 元テーブルの削除 drop table `nariDB_Django`.`GVIS_keihi` cascade / -- 新テーブルをリネームして元テーブル名に変更 alter table `nariDB_Django`.`$$GVIS_keihi` rename to `nariDB_Django`.`GVIS_keihi` / -- インデックスとユニーク制約の作成 create index IDX_keihi on `nariDB_Django`.`GVIS_keihi`(`workPeriod`,`workShubetsu`,`workPriority`,`Keihi_date`,`Kamoku`) / テンポラリテーブルに列追加したターゲットテーブルを作って、そこに元テーブルのデータを流し込み、元テーブル削除したらターゲットテーブルを名前変更してキーつけてくれる。 ...

djangoをdockerコンテナで利用(17) - djangoで帳簿運用

3か月の並行運用期間と過去データで検算 php版を最初に作ったときは、excelで検算してた。 webページをそのままexcelに貼り付けるだけじゃうまく行かない箇所は電卓。 今回は3月にdjango版がだいたいできたから、4月から入力しながら処理誤りを修正しつつ、php版の結果と比べてった。 処理をそろえて作ってるから当たり前なんやけど、1円単位で合計があったときはやっぱり嬉しい。 こういうとき ディスプレイが3枚 あるとチェックがめっちゃ楽。 入力は3か月やけど、帳簿は7年分を確認してった。 django版はちょっと細かめに計算。 その計算結果を使ってグラフ作らせたら、これまたパーセンテージが一致。 小数点第2位まで一致。 7年分見たとき、この数字が一致したときの快感はなんとも言えず気持ちよかった。 印刷でアセった 検索結果一覧画面を表示させておいて、これをpdf保管したい。 例えば現金出納帳は決まった年数保管しとかないといけない。 firefoxで見たら、なんじゃこりゃ。 ボタンとかロゴとかだけ表示されてるけど、数字があらへん。 cssのせい? djangoの中の何か設定? pipでなんかインストールいるんか? 小一時間ほどdjangoで印刷っていうのを調べたら、いろいろ結果が出てきた。 けっこう面倒くさい。 こんなんやってられへんし、もっと楽にできへんのかなぁってfirefox閉じてchromeで表示させたら、あっさり表示できた。 ブラウザ依存とか困るなぁ。 何年か前に「閉じる」のボタンを作ってたら、セキュリティか何かの都合でfirefoxもchromeも閉じてくれんようになった。 最近はjava scriptの解釈が変わったんかもしれんけど、また閉じれるようになった。 この印刷も何年かしたらちゃんと見えなくなるんとちゃうか。 フォームの箇所いらんから結果だけ印刷したいけど、まぁ数字は読めるしええか。 今年はいったんこれで完成。 どっかで解決方法見つけたら、pdf出力の方法探そっと。 1年かけて得られたもの php版の帳簿管理の仕組みから脱却してdjangoで動かそうとしたのが去年の今頃。 「pythonで扱うdjangoってどんなんやねん」から始まって、ssl利用とかpdfのデータベース保存とかグラフ作成とか、いろいろ挑戦してようやく完成。 google cloudの中のコンテナも用意できて、ローカルの開発環境とクラウドの本番環境を切り替えながら使うのもできるようになった。 コンテナ仮想化使ってるから、単純にアプリケーション作るための知識を得るだけじゃなく、アプリケーションインフラ寄りの知見も得られた。 日本語フォントのインストールとか、円グラフのライブラリをdjangoで使えるようにするのは苦労したなぁ。 djangoのモジュールのgitグラフを見ると、作って楽しかった履歴が見える。 できたつもりが、できてなかったり、思い出したら人に言えない恥ずかしいコミットもある。 最初はurls.py小さかったけど、こんなにデカなってた。 画面遷移がうまく行かんなぁって、コレ書き間違えてるのに気づくの時間かかったっけ。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 urlpatterns = [ path('login/', auth_views.LoginView.as_view(template_name='gvisWebApp/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(template_name='gvisWebApp/logout.html'), name='logout'), path('home/', gvis_base_views.home, name="home"), path('gvis_001_IntraIchiran/', gvis_base_views.gvis_001_IntraIchiran, name="gvis_001_IntraIchiran"), path('gvis_002_LogKensaku/', gvis_log_views.GvisLogList.as_view(), name="gvis_002_LogKensaku"), path('gvis_Complete/', gvis_base_views.gvis_Complete, name="gvis_Complete"), path('gvis_100_ShisanKensaku/', gvis_zaiko_views.GvisZaikoList.as_view(), name="gvis_100_ShisanKensaku"), path('gvis_101_ShisanDetail/<int:pk>/', gvis_zaiko_views.GvisZaikoDetail.as_view(), name="gvis_101_ShisanDetail"), path('gvis_102_ShisanCreate/', gvis_zaiko_views.GvisZaikoCreate.as_view(), name="gvis_102_ShisanCreate"), path('gvis_103_ShisanDelete/<int:pk>/', gvis_zaiko_views.GvisZaikoDelete.as_view(), name="gvis_103_ShisanDelete"), path('gvis_104_ShisanUpdate/<int:pk>/', gvis_zaiko_views.GvisZaikoUpdate.as_view(), name="gvis_104_ShisanUpdate"), path('gvis_105_GvisZaikoTENPU/<int:pk>/', gvis_zaiko_views.GvisZaikoTENPU.as_view(), name="gvis_105_GvisZaikoTENPU"), path('gvis_200_KokyakuKensaku/', gvis_cust_views.GvisMstCustomerList.as_view(), name="gvis_200_KokyakuKensaku"), path('gvis_201_KokyakuDetail/<int:pk>/', gvis_cust_views.GvisMstCustomerDetail.as_view(), name="gvis_201_KokyakuDetail"), path('gvis_202_KokyakuCreate/', gvis_cust_views.GvisMstCustomerCreate.as_view(), name="gvis_202_KokyakuCreate"), path('gvis_203_KokyakuDelete/<int:pk>/', gvis_cust_views.GvisMstCustomerDelete.as_view(), name="gvis_203_KokyakuDelete"), path('gvis_204_KokyakuUpdate/<int:pk>/', gvis_cust_views.GvisMstCustomerUpdate.as_view(), name="gvis_204_KokyakuUpdate"), path('gvis_205_GvisCustTENPU/<int:pk>/', gvis_cust_views.GvisMstCustomerTENPU.as_view(), name="gvis_205_GvisCustTENPU"), path('gvis_300_TorihikiKensaku/', gvis_tran_views.GvisTransactionList.as_view(), name="gvis_300_TorihikiKensaku"), path('gvis_301_TorihikiDetail/<int:pk>/', gvis_tran_views.GvisTransactionDetail.as_view(), name="gvis_301_TorihikiDetail"), path('gvis_302_TorihikiCreate/', gvis_tran_views.GvisTransactionCreate.as_view(), name="gvis_302_TorihikiCreate"), path('gvis_303_TorihikiDelete/<int:pk>/', gvis_tran_views.GvisTransactionDelete.as_view(), name="gvis_303_TorihikiDelete"), path('gvis_304_TorihikiUpdate/<int:pk>/', gvis_tran_views.GvisTransactionUpdate.as_view(), name="gvis_304_TorihikiUpdate"), path('gvis_305_GvisTranTENPU/<int:pk>/', gvis_tran_views.GvisTransactionTENPU.as_view(), name="gvis_305_GvisTranTENPU"), path('gvis_400_KatsudoKensaku/', gvis_work_views.GvisWorkList.as_view(), name="gvis_400_KatsudoKensaku"), path('gvis_401_KatsudoDetail/<int:pk>/', gvis_work_views.GvisWorkDetail.as_view(), name="gvis_401_KatsudoDetail"), path('gvis_402_KatsudoCreate/', gvis_work_views.GvisWorkCreate.as_view(), name="gvis_402_KatsudoCreate"), path('gvis_403_KatsudoDelete/<int:pk>/', gvis_work_views.GvisWorkDelete.as_view(), name="gvis_403_KatsudoDelete"), path('gvis_404_KatsudoUpdate/<int:pk>/', gvis_work_views.GvisWorkUpdate.as_view(), name="gvis_404_KatsudoUpdate"), path('gvis_405_GvisWorkTENPU/<int:pk>/', gvis_work_views.GvisWorkTENPU.as_view(), name="gvis_405_GvisWorkTENPU"), path('GvisWorkCopy/', gvis_work_views.GvisWorkCopy, name="GvisWorkCopy"), path('GvisWorkMonthlyCopy/', gvis_work_views.GvisWorkMonthlyCopy, name="GvisWorkMonthlyCopy"), path('gvis_500_KeihiKensaku/', gvis_keihi_views.GvisKeihiList.as_view(), name="gvis_500_KeihiKensaku"), path('gvis_501_KeihiDetail/<int:pk>/', gvis_keihi_views.GvisKeihiDetail.as_view(), name="gvis_501_KeihiDetail"), path('gvis_502_KeihiCreate/', gvis_keihi_views.GvisKeihiCreate.as_view(), name="gvis_502_KeihiCreate"), path('gvis_503_KeihiDelete/<int:pk>/', gvis_keihi_views.GvisKeihiDelete.as_view(), name="gvis_503_KeihiDelete"), path('gvis_504_KeihiUpdate/<int:pk>/', gvis_keihi_views.GvisKeihiUpdate.as_view(), name="gvis_504_KeihiUpdate"), path('GvisKeihiCopy/', gvis_keihi_views.GvisKeihiCopy, name="GvisKeihiCopy"), path('GvisKeihiMonthlyCopy/', gvis_keihi_views.GvisKeihiMonthlyCopy, name="GvisKeihiMonthlyCopy"), path('gvis_510_KamokuKensaku/', gvis_kamoku_views.GvisKamokuList.as_view(), name="gvis_510_KamokuKensaku"), ## 科目画面ではcreate/detail viewを扱わず、削除と更新のみ path('gvis_513_KamokuDelete/<int:pk>/', gvis_kamoku_views.GvisKamokuDelete.as_view(), name="gvis_513_KamokuDelete"), path('gvis_514_KamokuUpdate/<int:pk>/', gvis_kamoku_views.GvisKamokuUpdate.as_view(), name="gvis_514_KamokuUpdate"), path('GvisKamokuCopy/', gvis_kamoku_views.GvisKamokuCopy, name="GvisKamokuCopy"), path('gvis_600_ChoboKensaku/', gvis_chobo_views.GvisChoboList.as_view(), name="gvis_600_ChoboKensaku"), path('gvis_700_KoteishisanKensaku/', gvis_koteishisan_views.GvisKoteishisanList.as_view(), name="gvis_700_KoteishisanKensaku"), path('gvis_800_GenkinKensaku/', gvis_genkin_views.GvisGenkinList.as_view(), name="gvis_800_GenkinKensaku"), path('gvis_900_ShiwakeKensaku/', gvis_shiwake_views.GvisShiwakeList.as_view(), name="gvis_900_ShiwakeKensaku"), path('ENplot/<int:year>', gvis_chobo_views.get_ENpng, name='ENplot') # 円グラフを描くための設定 数年したらまたpython&djangoの環境から脱却して別の実装へ引っ越すかもしれんけど、別の言語へ引っ越すための勉強になった。 ...

 ⭐️

djangoをdockerコンテナで利用(16) - djangoで科目単位の集計

集計処理やっと作るところまで来た。 最初の頃に グラフ作れるかなって やってのたと、 集計 を組み合わせる。 結論 テストデータはこんな感じ。 月単位で経費を計上したレコードがある。 見た目ほぼそのままdockerコンテナであるmariadbのテーブル上でレコードとして存在する。 これを、縦軸に科目、横軸に月として、その1年の金額と比率を集計させる。 今月売上なんぼ、機材なんぼ、新聞図書費なんぼとかわかる。 帳簿の一部としてwebページをpdfにして保管するから、グラフはそのとき省く様ためグラフ表示のスイッチをつけとく。 さらに集計結果を円グラフ表示させる。 今月は旅費かかったなーとか、交際費もう少し使っても大丈夫かなーとか目安がわかる。 現行php版での処理をdjangoで全部作り直したとき、過去7年分の経費レコードに対する金額合計が1円の差異もなく集計・表示されたときは嬉しかった。 あと少しでphpのdockerコンテナとおさらばできる。 科目単位の集計 今までのdjango作りこみは実在するテーブルに対応したモデルだけを扱ってきた。 今回は複数テーブルから読み込んだ結果を集計するモデルを作っていく。 「見せ方」を先に考えるから、そのためのモデルをまずは準備して次にテンプレートを準備してく。 modelsの準備 結局は科目の一覧なので、ベースは科目のマスタ(GVIS_mst_kamoku)。 そこに、月単位の合計を肉付けしてモデルを作る。 1月から12月までの列を用意して、経費テーブル(GvisKeihi)の中にある科目で集計するメソッドを定義する。 以下、帳簿の一部であるGvisChobo.pyのモデル定義。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 from django.db import models from django.utils import timezone from pymysql import NULL from datetime import datetime ## 日付取得のため from datetime import date, timedelta ## マスターテーブル使うため from gvisWebApp.models.GvisMaster import GvisMstKeihishubetsu,GvisMstKamoku from gvisWebApp.models.GvisKeihi import GvisKeihi ## マスターテーブル絞り込みのため from django.db.models import Q,Sum class GvisChobo(models.Model): kamokuno = models.IntegerField(verbose_name='科目No',db_column='kamokuNo') # Field name made lowercase. def __str__(self): return str(self.kamokuno) kamokuname = models.CharField(verbose_name='科目名',db_column='kamokuName',max_length=20) # Field name made lowercase. def __str__(self): return self.kamokuname kamokusetsumei = models.CharField(verbose_name='科目説明',db_column='kamokuSetsumei', max_length=200) # Field name made lowercase. def __str__(self): return self.kamokusetsumei hyojiorder = models.IntegerField(db_column='hyojiOrder') # Field name made lowercase. def __str__(self): return str(self.hyojiorder) keihitaisho = models.IntegerField(db_column='keihiTaisho') # Field name made lowercase. def __str__(self): return str(self.keihitaisho) def get_kng01(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,1,1),date(year,2,1) - timedelta(days=1)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng def get_kng02(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,2,1),date(year,3,1) - timedelta(days=1)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng : (中略) : def get_kng12(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,12,1),date(year,12,31)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng def get_KamokuTotal(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,1,1),date(year,12,31)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng class Meta: managed = False db_table = 'GVIS_mst_kamoku' 例えばget_kng12はフォームで受け取った年で、12月の科目を集計してる。経費テーブルには「003-研究開発費」みたいな感じで、科目の頭に3桁の数字とハイフンが入っているから、それをキーにしてfilterしてる。 ...

 ⭐️

djangoをdockerコンテナで利用(15) - djangoでsql直接発行

djangoでレコードの集計してたら、どうしてもできない集計があることに気づいた。 仕方がないので、直接sql発行して集計させることにした。 sqlを文字列として準備し発行すると、仮にexceptionが発生したときにもそれをエラーログとして出力させるようにした。 ログ出力 はmariadbに出力するようにしてる。 今回はレコード集計結果を作ったのでそのメモ。 結論 djangoで経費のレコードを処理する画面を作ってる途中。 これから「編集」と「操作」の列にボタン足して編集・コピー・削除の機能をつけてこうとしてる。 他の画面で既に「編集」と「操作」は作ってあるから、djangoのviewsにはコピーして作れば余裕。 経費テーブルには、かかった費用の目安を記録しときたいから、自作の科目も含んでて、実際の「水道代」とか「外食費」もつけて台帳管理してる。 自宅で業務をしてると「水道光熱費」ってのは、実生活でかかる水道代や電気代を業務と生活で按分しなきゃいけないから、全部を計上しちゃいけない。 確定申告で使う経費科目は決まっているから、自作の経費科目は経費計上しないようにしたい。 けれど、djangoではその科目に応じた集計をさせられない場面があった。 予想してたけど、やっぱりできん集計あるんやなぁ。 (自分がまだ見つけられてないだけかもしれん) さっさと進めて作りたかったから、直接SQLの文字列を発行して集計結果を表示させるようにした。 djangoの基本機能で集計できなかったのは、経費合計。 理由は経費テーブルから外部参照する科目テーブルに、経費対象の列があって、外部参照する列をdjangoのfilterで指定できなかったから。 指定するとエラーになって、実テーブルに存在する項目しか指定を許可してくれなかったから。 その他の、医療費控除とか売上合計なんかの科目狙い打ち集計はできてた。 自分のテーブル設計がマズいのかもしれんけど、既存のphp版からの移行作成やから、保管構造は変えない方針。 (idの列は足したけど・・・) 処理優先で考えるんじゃなく、データベース優先で考えるから、djangoの機能を使えるところだけ使って、実際の集計はsql書くことにした。 既存のphp版にある過去7年分、84か月分の経費合計がきっちりあってた。1円も狂ってなくて気持ちよかったなぁ。 djangoは「SQL書かなくても動く」ってのがいいところ、みたいな書き方を見かけるけど、DBMSの集計機能を使ってSQLで書いたほうがいいこともあると思う。 実際の開発でSQL書けない人がたまにいるけど、RDBを扱うときにSQL書けなかったら、本番開始後のDB関連障害や高速化に対応できないんじゃないかとも思う。 例えばoracleからpostgresqlに移行するときのことを考えて、sqlは一切書かずに全部djangoに任せるっていうのはいいことかもしれんけど、そういう見込みがないんやったらベタのSQL書いて楽したほうがええんとちゃうか? サンプルデータ 例えばこんなデータがあったとする。 月間の売上とか経費が入ってる。 経費テーブル workPeriodは、経費計上の年月だけ使ってるから、全部1日の0:00:00って入ってる。 Kamokuは、科目テーブルにある科目番号と科目名が埋め込んである。 id workPeriod workShubetsu workPriority Keihi_date Kamoku Tehai Kng Biko 9058 2022/03/01/火 0:00:00 1yan 1001 2022/03/10/木 0:00:00 008-給料賃金 給与 60000 20140924申請の青色事業者専従者給与に関する届出書により10万円を目標に計上。 9059 2022/03/01/火 0:00:00 1yan 1002 2022/03/10/木 0:00:00 020-水道光熱費 光熱費 10000 50%を事業用の電気代とする。月平均2万円x50%=1万円。 9068 2022/03/01/火 0:00:00 1yan 1003 2022/03/10/木 0:00:00 025-通信費 インターネット/電話利用料 10000 電話とインターネットは50%を事業用の電気代とする。月平均2万円x50%=1万円。 9060 2022/03/01/火 0:00:00 2kgc 1010 2022/03/31/木 0:00:00 101-現金売上 amazon販売 0 物販(3/xx) 9077 2022/03/01/火 0:00:00 2kgc 1020 2022/03/10/木 0:00:00 102-預金売上 お客様 100000 xxx案件 9074 2022/03/01/火 0:00:00 2kgc 1047 2022/03/31/木 0:00:00 023-損害保険料 xx保険 6550 エージェント会社提供の掛け捨て保険 9087 2022/03/01/火 0:00:00 2kgc 1068 2022/03/05/土 0:00:00 003-研究開発費 定食屋 1630 IT市場調査。昼食。 9070 2022/03/01/火 0:00:00 2kgc 1072 2022/03/06/日 0:00:00 001-打合会議費 喫茶xx 2480 月初打合せ 9101 2022/03/01/火 0:00:00 2kgc 2019 2022/03/20/日 0:00:00 003-研究開発費 apple 4787 mp4解析用 9055 2022/03/01/火 0:00:00 3ikk 1042 2022/03/31/木 0:00:00 038-外食費 外食費累積 1467 目安 9056 2022/03/01/火 0:00:00 3ikk 1043 2022/03/31/木 0:00:00 039-食費 食費累積 74120 目安 9051 2022/03/01/火 0:00:00 3ikk 1045 2022/03/31/木 0:00:00 099-預金残高 銀行残高 0 残高確定 9085 2022/03/01/火 0:00:00 3ikk 1046 2022/03/31/木 0:00:00 040-水道代 大阪市水道局 3842 1月分水道代。1月13日検針。22立米。(クレカ引き落とし) 9054 2022/03/01/火 0:00:00 3ikk 1053 2022/03/31/木 0:00:00 041-電気代 関西電力 19738 3月分電気代。919kwh。 経費種別テーブル workShubetsuは経費の種別で、djangoのtemplatesで表示させるときの色指定が一緒に入ってる。 ...

 ⭐️