目次
アプリのモデル定義 (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 を 1 クラス 1 ファイルに分割する
標準の 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.py で Media モデルを定義する。
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制約
トラブルシューティング
モデル定義が No module named 'xxxxx' エラーを起こす
$ 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