Django開発ではまったこと

はじめてのDjango開発で、ひっかかったところ、はまったところの記録。

1)拡張テンプレート側のstaticのロードエラー

ベース側で「{% load static %}」しているので、なんとなく拡張側は要らないような気でいたら、以下エラーが出た。

Invalid block tag on line **: 'static', expected 'endblock'. Did you forget to register or load this tag?

拡張ファイル側でも「static」を使う場合は、「{% load static %}」する必要がある。

※「{{ block.super() }} 」した場合に、その中で「static」を使われている場合も、「{% load static %}」する必要がある。

2)Django Debug Toolbarが表示されない

Visual Studio からDjangoの開発用サーバーで実行すると、ツールバーが表示されない。Chromeのエラーを見ると、toolbar.jsの読み込みがはじかれている。

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain".

とりあえず、setting.pyに以下を追加することで解決。

# For Debug Toolbar
if DEBUG:
    import mimetypes
    mimetypes.add_type("text/javascript", ".js", True)

3)Visual Studioのサンプルの文字コード

サンプルのDjangoのWebアプリのテンプレートの文字コードがSJISのようで、修正しながら、テンプレート内に日本語を書くと、実行時にエラーになった。他のエディタで一度UTF-8で一度保存してから修正する必要あり。

4)アドオンhumanizeのintcomma

自分のプロジェクトの言語設定の問題か、桁区切りをつけるintcommaがうまく動作しなかった。

https://docs.djangoproject.com/ja/3.1/ref/contrib/humanize/#intcomma

ソースを見ると、第二引数で言語設定を無視できるよう。

(GitHubソース)contrib/humanize/templatetags/humanize.py

以下のように、Falseを設定することで回避できた。

<div class="text-right>{{ report.count_visit|intcomma:False }}</div>

DjangoでWebアプリ

既存システムのDBを使って、Djangoで新たなWebアプリを作っている作業メモ。

1.開発環境と既存DBの取り込み

とりあえず、Visual Studio Community 2019で、既存DBのモデルに取り込みまでは、以下で行った。

2.アプリ開発

チュートリアルを参考に改造していく。

(Django公式)はじめての Django アプリ作成、その 1 | Django ドキュメント

2.1 DBの内容をページに表示

まずは、既存DBのモデルにてデータを取得し、ページに表示する。流れとしては、Viewでmodelを使ってデータを取得し、それをテンプレートに渡して表示させる。

1)ビュー

以下を参考に、モデルを取り込んで、データをテンプレートに渡すようにする。

(Django公式)実際に動作するビューを書く

app/views.pyを修正していく。

①読み込みたいmodelをimport
from .models import DBモデル
②modelを操作してデータを取得

データベース操作について、公式サイトのリンクが以下にまとめてくれてあるので、ありがたく参考にさせてもらう。

(Qiita)Django データベース操作 についてのまとめ

2)テンプレート

app/templates/app以下のテンプレートを修正していく。テンプレートの記述言語についての説明は以下ページ。

(Django公式)

テンプレート

The Django Template Language

Viewから渡されたデータは、「{{ 変数名 }}」と記述して使えるので、それをページ内に表示させる。

2.2 カスタムマネージャーの作成

DB取得等のロジックをViewの中に色々書くのもいまいちなので、カスタムマネージャーを作成する。

(Django公式)マネージャーのカスタマイズ

上記の日本語版は、翻訳が微妙で間違った解釈になるところがあるので、英語版を読んだ方が良さそう。

(Django公式)Custom managers

拡張クラスにメソッドを定義、あるいはget_querysetを書き換える等をコーディングするなり、QuerySetを定義するなりする。以下に4パターンの方法が記載されている。

(Django公式ドキュメント)

①カスタムMangerにメソッド追加する方法

Adding extra manager methods

②カスタムMangerの初期クエリセットを変更する方法

Modifying a manager’s initial QuerySet

③QuerySetを拡張してメソッド追加する方法

Calling custom QuerySet methods from the manager

④QuerySetを複数拡張する場合に、Managerをクエリセットから定義できる方法

Creating a manager with QuerySet methods

上記から適切な方法で実装していく。

1)カスタムマネージャーの定義

app/managers.pyを追加して、カスタムマネージャーを定義する。

"""
Definition of DB managers.
"""

from django.db import models

# Managerの拡張クラスを定義
class XxxxxxManager(models.Manager):
    :

データの絞り込みは、filterを使う。

(Django公式ドキュメント)

フィルタを用いて特定のオブジェクトを取得する

フィールドルックアップ

2)モデルの修正

app/models.pyの修正して、モデルのobjectsを書き換える、あるいは目的に応じたmanagerを取得するメソッドと追加する。

3)有効期間内のデータを対象とする例

テーブル(Information)に有効期間として、from_timeとto_timeを持っていて、現在有効なデータだけを対象とする場合の例。「②カスタムMangerの初期クエリセットを変更する方法」で実装。

① manager.py
"""
Definition of DB managers.
"""

from django.db import models
from django.db.models import Q
from django.db.models.functions import Now


# Information
class InformationManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(
            Q(from_time__lte=Now()) & Q(to_time__gt=Now()))

filterに、「Q(from_time__lte=Now()) & Q(to_time__gt=Now())」とすることで、「from_time <= CURRENT_TIMESTAMP AND to_time > CURRENT_TIMESTAMP」という条件になる。

(Django公式ドキュメント)

Q オブジェクトを用いた複雑な検索

Now関数

② models.pyの修正
"""
Definition of models.
"""

from django.db import models
from .managers import InformationManager


# Create your models here.

class Information(models.Model):
    id_information = models.AutoField(primary_key=True)
    from_time = models.DateTimeField(blank=True, null=True)
    to_time = models.DateTimeField(blank=True, null=True)
    title = models.CharField(max_length=128, blank=True, null=True)
    detail = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField()
    updated_at = models.DateTimeField()

    objects = models.Manager() # The default manager.
    news = InformationManager() # Custom manager

    class Meta:
        managed = False
        db_table = 'information'

Viewでは、Information.newsで対象データを取得する。

2.3 デバッグ

Django Debug Toolbarを入れる。

Django Debug Toolbar

ドキュメントに従い設定したが、Visual Studio からDjangoの開発用サーバーで実行すると、ツールバーが表示されない。

Chromeのエラーを見ると、toolbar.jsの読み込みがはじかれている。

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain".

とりあえず、setting.pyに以下を追加することで解決。

# For Debug Toolbar
if DEBUG:
    import mimetypes
    mimetypes.add_type("text/javascript", ".js", True)

3.UIデザイン

デザインは苦手なので、Bootstrapのサンプルを参考にする。

https://getbootstrap.jp/docs/4.5/examples/

1)最新のBootstrapを入れる

app/static/app/content,scripts下のBootstarp、JQuery、Popper等の必要なものを入れる。

CDNを利用するのがいいのかもしれないが、とりあえず開発時点ではstaticに取り込む。

2)サンプルのCSS,JSを入れる

使うサンプルのCSS,JSもapp/static/app/content,scripts下に入れる。

3)サンプルを参考にテンプレートを作成していく。

トップページは、Pricingを参考に。管理画面はDashboardを基に作ることにする。

4.セキュリティー設定

1)admin

adminについて、必要ないなら消す。カスタマイズして使っていく予定なら、IP制限を入れる。以下を利用した。

django-admin-ip-restrictor

CentOS7に最新のPostgreSQL

テスト環境のCentOS7に入れてあるPostgreSQLが古いので、バージョンアップして最新に。その時の、作業メモ。

1.インストール

yumのままだとPostgreSQL9.2になっているので、最新をRPMから入れる。

(PostgreSQL公式)PostgreSQL: Linux downloads (Red Hat family)

このページで、1.バージョン、2.プラットフォーム、3.アーキテクチャーを選べば、4に必要なコマンドが出てくるので、それを実行。

$ yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
$ yum install -y postgresql13-server
$ /usr/pgsql-13/bin/postgresql-13-setup initdb
$ systemctl enable postgresql-13
$ systemctl start postgresql-13

事前に、前のバージョンは、停止して、自動起動も止める。

$ systemctl stop postgresql
$ systemctl disable postgresql

環境設定等は、以下が参考になる。

(Qiita)PostgreSQL スーパーユーザの環境変数設定

2.DB復元

バックアップファイルから、DBを復元する。

1)postgresユーザーになって、psqlコマンドを起動し、データベースとロールを作成。

$ su - postgres
$ psql
psql (13.1)
Type "help" for help.
postgres=# CREATE DATABASE xxxxxx;
CREATE DATABASE
postgres=# CREATE ROLE xxxxxx SUPERUSER LOGIN PASSWORD 'xxxxx';
CREATE ROLE
postgres=# \q

2)DBの復元

$ pg_restore -d xxxxx バックアップファイル

3.接続設定

新しいバージョンの定義ファイルを修正して、従来と同じ方法で接続できるようにする。

(定義ファイルの場所)

/var/lib/pgsql/13/data/

開発環境からの接続を許可するように、以下ファイルを修正。

$ diff pg_hba.conf.org pg_hba.conf
86a87
host all all 111.111.111.111/32 scram-sha-256    ※111.111.111.111:開発環境のIPアドレス

$ diff postgresql.conf.org postgresql.conf
62a63
listen_addresses = '*'

ファイアウォールでPostgreSQLのポートが閉じられているなら、開く。

4.ポート変更する場合

セキュリティー上、あるいは複数バージョンを同時に立ち上げる等でポート変更する場合。

1)設定ファイルのポートを変更して再起動

# diff postgresql.conf.org postgresql.conf
64c64
< #port = 5432                          # (change requires restart)
---
> port = 9999                           # (change requires restart) 

# systemctl restart postgresql-13

2)ファイアウォールのPostgreSQLのポートを変更、または追加

両方のバージョンを並行運用することも考えて、13は別サービスとして登録。

サービス定義ファイルの場所に移動して、サービス定義ファイルをコピーして、ポートを修正する。

# cd /usr/lib/firewalld/services
# cp postgresql.xml postgresql-13.xml
# vi postgresql-13.xml   ※portの設定を変更
# firewall-cmd --permanent --add-service=postgresql-13
# firewall-cmd --reload
# firewall-cmd --list-all ※確認

※ちなみに、yumで入れたPostgreSQL9.2もポート番号を変えたい場合、サービス起動ファイルに、ポートが書かれているのでこちらを変更する必要がある。

# vi /usr/lib/systemd/system/postgresql.service
    ※Environment=PGPORT=5432 を変更して、サービス再登録
# systemctl stop postgresql
# systemctl disable postgresql
# systemctl enable postgresql
# systemctl start postgresql
# systemctl status postgresql  ※ポート変更されていることを確認

Visual StudioでDjango

Visual Studio Community 2019 で、Djangoで開発を始めたので、作業メモ。とりあえず、Microsoftのドキュメントからチュートリアルを参考に。

(MS公式)チュートリアル: Visual Studio での Django Web フレームワークの概要

チュートリアルは前の2017バージョンだけど参考に、軽く動かしながら、実際に作りたいものに変えていく。

【主な変更作業】

Webプロジェクト テンプレートから、自分用に変更していく。

(MSサイト)手順 4: Django Web プロジェクト テンプレートを使用する

1 Viewの変更

まずは見た目からということで、自分の作りたいページ構成に変えていく。

  • app/templates/layout.html:タイトル、メニュー、フッター等を修正
  • app/views.py:templateの中で表示するデータを修正

2 DB変更

DBを、業務で使っているPostgreSQLに変更する。使うドライバとしては、以下のPsycopgがよく使われているらしいので、それを使うことにする。

(Psycopg公式)Psycopg – PostgreSQL database adapter for Python

1)ドライバのインストール

psycopg2パッケージをインストールする。インストール方法は以下ページを参考に。

(MS公式)[Python 環境] ウィンドウ タブ リファレンス

ソリューションエクスプローラーの[Python環境]>[Env]を右クリックして[Pythonパッケージの管理]からも行ける。

2)DB接続の設定

以下ページを参考に、settings.pyのDATABAESを修正。

(django公式)djangoドキュメント – Settings -DATABASES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '111.111.111.1111',
        'PORT': '', # 空白の場合はデフォルト
    }
}

3)既存の業務DBの定義を取り込む

以下を参考に、models.pyに既存DBの定義を追加する。

(Djangoi公式)レガシーなデータベースと Django の統合

ソリューションエクスプローラーから[Python環境] を右クリックして、[すべてのPython環境を表示]して、実行環境を選択して、下の[PowerShell で開く]。

PowerShellで、以下コマンドを実行。

$ python manage.py inspectdb

以下のエラーが出て、うまく定義を作成できないよう。

Unable to inspect table 'XXXXXXXXXX'
The error was: syntax error at or near "WITH ORDINALITY"
LINE 6: FROM unnest(c.conkey) WITH ORDINALITY co…

PostgreSQLがVer9.2と古くて対応していないので、いい機会なのでバージョンアップすることに。

PostreSQLをバージョン13にしたら、問題なくinspectdbができたので、models.pyに定義を追加する。

4)DBのマイグレーション

PostgreSQLにadmin関係のテーブルを作成する。Microsoftのドキュメントの手順をい参考に。

(MS公式)手順 6-1:プロジェクトを作成し、データベースを初期化する

ソリューションエクスプローラーで、プロジェクトを右クリックして、[Python]>[Django で移行を実行する]を行う。その後、[Django でスーパーユーザーを作成する]を実行。

3.setting.pyの修正

日本語設定等を行う。

(Django公式)設定 | Django ドキュメント

とりあえず、変えたところは以下。

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

【アプリ作成】

Django公式のチュートリアルを参考に、仕組みを勉強しながら作業。

4.Djangoのバージョンアップ

Visual Studio 2019 のプロジェクトテンプレートは、Django2.2なので、最新のDjango3.1に変更した。

プロジェクトフォルダ直下のrequirement.txtのバージョンを修正する。

django~=3.1

Python環境の実行環境(ディフォルトならenv)を選択して、[パッケージ(PyPI)]を選択して、表示されている「Django2.2.*」の横の上矢印でバージョンアップするか、プロジェクトを再読み込みすれば画面上部にメッセージが出るのでクリックしてバージョンアップ。

テンプレートファイルの、staticsfilesの読み込みが、エラーになるので、テンプレートファイルを修正する。

【旧】{% load staticfiles %}
↓
【新】{% load static %}

5.テストについて

https://docs.microsoft.com/ja-jp/visualstudio/python/unit-testing-python-in-visual-studio?view=vs-2019

CentOSサーバーにGit

GitHubにソースを置きたくないので(一応、4月から無料でもprivateにできるが)、自前のサーバーにGitを立てることにした。Gitの公式ドキュメントは以下。

Gitドキュメント(日本語)

とりあえず、Gitサーバー立てるのは、以下を参考に。

4.4 Gitサーバー – サーバーのセットアップ

0)方針

  • 個人の開発端末のVisual Studio 2019のローカルレポジトリーのバックアップ用。
  • 端末は複数(自宅、外)あるので、共有とする。
  • 公開サーバー上に置くので、アクセスはポート変更済みのSSHで鍵認証。
  • ユーザーはgit操作しかできないユーザーとする。

1)Gitインストール

$ yum install git

2)Gitユーザー作成

git用のユーザーを作成する。この時、ログインシェルをgitに制限したものgit-shellを指定。

$ adduser --shell=/usr/bin/git-shell git

3)SSH公開鍵の登録

クライアント側の公開鍵を登録するために、gitユーザーにsuする。

$ su -s /bin/bash - git

クライアント側(開発PC端末)のSSH公開鍵(/tmp/id_rsa.john.pub)を登録する。※公開鍵が未作成の場合は、以下手順(5-1)で作成した公開鍵を登録。

$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
 ※viで編集するでもOK

4)プロジェクトの初期化

空の共有のhogeプロジェクトを作成。

$ cd
$ mkdir hoge.git
$ cd hoge.git
$ git init --bare --shared
 ※gitユーザーでしか使わないのが、後の為、一応、shared

5)Windows側のSSH設定

Windows PowerShellを起動して、SSHの設定を行う。ちなみに、Visual Studio 2019のGitで使うSSHコマンドは以下に入っている

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\usr\bin

5-1)SSH公開鍵の作成

ssh-keygenコマンドで、鍵を作成する。鍵を作成したら、公開鍵(端末側の、~/.ssh/id_rsa.pub)を、サーバー側の~/.ssh/authoraized_keysに追加登録する。※上記手順3にて

4.3 Gitサーバー – SSH 公開鍵の作成

$ ssh-keygen

5-2)既知ホストの追加&接続確認

Gitサーバー(xxx.gijutsu.comで、SSHポートが9999の場合)に接続して、クライアント側の既知ホストに登録する。

$ ssh -p 9999 -l git xxx.gijutsu.com

この時、既知ホストに追加するか聞いてくるので、yesを入力。その後は、以下のシェルエラーとなればOK。

Last login: Tue Dec 1 10:13:25 2020
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to xxx.gijutsu.com closed.

6)Visual StudioからのPush

作成したGitサーバーのhogeプロジェクトにプッシュする場合は、リモートURLは以下を指定。

ssh://git@xxx.gijutsu.com:9999/~/hoge.git

Visual Studio 2019では、「Git 」から「Gitレポジトリの作成」で、「既存のリモート」を選択して、上記のリモートURLを入力する。

Visual Studio 2019 - Gitレポジトリの作成