python:django:model_definition

アプリのモデル定義 (django_app/models.py)

Django アプリのモデル定義ファイルは、manage.py startapp で自動生成された状態では単一の Python モジュールファイルになっている。しかし、ほとんどのプロジェクトではそれなりの規模になると思われるので、モデルクラス 1 つにつき 1 Python ファイルに分けた方が保守性が良いと思う。

django_project ディレクトリ
+ django_app ディレクトリ
| + __init__.py このディレクトリが Python パッケージであることを Python に知らせる。
| + admin.py Django アプリの管理サイトを記述するファイル。
| + apps.py Django アプリの構成クラスを記述するファイル。
| + models.py Django アプリのモデル定義ファイル。
| + tests.py Django アプリのテストを記述するファイル。
| + views.py Django アプリのビューを記述するファイル。
| + migrations ディレクトリ
|| + __init__.py このディレクトリが Python パッケージであることを Python に知らせる。

標準の models.py は以下のような内容である。

models.py
from django.db import models
 
# Create your models here.

Python はディレクトリに __init__.py (内容は空でもよい) を置くと、ディレクトリ全体をパッケージと見なすようになる。このことを利用して models.py を削除して models ディレクトリとその中に __init__.py を置くようする。

django_project ディレクトリ
+ django_app ディレクトリ
| + __init__.py このディレクトリが Python パッケージであることを Python に知らせる。
| + admin.py Django アプリの管理サイトを記述するファイル。
| + apps.py
| + models ディレクトリ Django アプリのモデル定義パッケージ。
|| + __init__.py このディレクトリが Python パッケージであることを Python に知らせる。

そして、例えば media.pyMedia モデルを定義する。

django_project ディレクトリ
+ django_app ディレクトリ
| + models ディレクトリ Django アプリのモデル定義パッケージ。
|| + __init__.py このディレクトリが Python パッケージであることを Python に知らせる。
|| + media.py Media モデルの定義。

Python のパッケージ内参照 (from . import name) を利用して記述すると良い。
6. モジュール — Python 3.9.1 ドキュメント - 6.4.2. パッケージ内参照

django_app/models/__init__.py
# -*- encoding: utf-8 -*-
from .media import Media

.media と記述することで models パッケージ内の media モジュール (media.py) から import するように Python に指示できる。

django_app/models/media.py
# -*- encoding: utf-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _
 
class Media(models.Model):
    media_hash = models.CharField(_('media hash'), max_length = 128, db_index=True) # メディアハッシュ
    title      = models.CharField(_('title'),      max_length = 128, blank=True)    # タイトル
    artist     = models.CharField(_('artist'),     max_length = 128, blank=True)    # アーティスト
    album      = models.CharField(_('album'),      max_length = 128, blank=True)    # アルバム
    year       = models.CharField(_('year'),       max_length = 4,   blank=True)    # 西暦
    track      = models.IntegerField(_('track'),   blank=True)                      # トラック
    genre      = models.IntegerField(_('genre'),   blank=True)                      # ジャンル
    file_path  = models.CharField(_('file path'),  max_length = 128, blank=True)    # ファイルパス
    file_size  = models.CharField(_('file size'),  max_length = 128, blank=True)    # ファイルサイズ
    time_stamp = models.DateTimeField(_('time stamp'), max_length = 128, blank=True) # 更新日時
    youtube_id = models.CharField(_('youtube id'), max_length = 128, blank=True)    # YouTube ID
    # メタ情報
    class Meta:
        app_label = 'django_app'                # アプリケーション名
        verbose_name = _('Media')               # 単数形名称
        verbose_name_plural = _('Medias')       # 複数形名称
        db_table = 'vlc_media'                  # テーブル名
        ordering = ('artist', 'album', 'track',) # ソート列
        unique_together = (('media_hash'),)     # unique制約
$ python manage.py
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/tomoyan/py3_djangoapp/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/home/tomoyan/py3_djangoapp/lib/python3.7/site-packages/django/core/management/__init__.py", line 377, in execute
    django.setup()
  File "/home/tomoyan/py3_djangoapp/lib/python3.7/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/tomoyan/py3_djangoapp/lib/python3.7/site-packages/django/apps/registry.py", line 114, in populate
    app_config.import_models()
  File "/home/pi/py3_musicapp/lib/python3.7/site-packages/django/apps/config.py", line 211, in import_models
    self.models_module = import_module(models_module_name)
  File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/tomoyan/py3_djangoapp/django_project/django_app/models/__init__.py", line 2, in <module>
    from media import Media
ModuleNotFoundError: No module named 'media'

Django アプリのモデル定義パッケージの __init__.py を以下のように記述してはいけない。

django_app/models/__init__.py
# -*- encoding: utf-8 -*-
from media import Media

Python のパッケージ内参照 (from . import name) を利用して、パッケージ内の media モジュールから import するように記述する。

django_app/models/__init__.py
# -*- encoding: utf-8 -*-
from .media import Media
  • python/django/model_definition.txt
  • 最終更新: 2020/12/25 06:40
  • by ともやん