背景
cronを使ったバッチ処理などで、アプリ内のモデルを使ってDBを読み書きしたい場合があります。
しかし、コマンド用の.pyファイルを上位ディレクトリに置いて、アプリ内のモデルをimportして使おうとすると、ValueError: attempted relative import beyond top-level package
とエラーが出て、アプリのディレクトリ外からは呼び出せません。
そこで、カスタム django-admin コマンドとして実装します。
詳しくは、公式ドキュメントの「カスタム django-admin コマンドの実装」に解説があります。
環境は、Python 3.7.0、Django 2.1.3 です。
作成手順
- アプリ内に、maangement/commands ディレクトリを作成する
- その中に、コマンド名.pyを作成する(以下では、crawler.py)
以下のようなフォルダ構成になります。
├── app1
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── management
│ │ └── commands
│ │ └── crawler.py ★これ
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── myproject
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
- コマンド名.pyの中身を記述する
crawler.py
from django.core.management.base import BaseCommand, CommandError
from app1.models import Topic
class Command(BaseCommand):
help = 'crawler for test.'
def handle(self, *args, **options):
t = Topic.objects.all()
self.stdout.write(self.style.SUCCESS("all Topic=%s" % t))
- 詳細
from django.core.management.base import BaseCommand, CommandError
- handleメソッドに、実行したい内容を記述
- モデルもimportして利用できる
- 文字列を出力したい場合は、self.stdout経由で出力
- help変数に説明を記述
確認
-
$ python manage.py help
で表示されるコマンド一覧に、追加したコマンドが表示される
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[app1]
crawler
(略)
-
$ python manage.py help crawler
で、作成したコマンドのヘルプが表示される
usage: manage.py crawler [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color]
crawler for test.
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
-v {0,1,2,3}, --verbosity {0,1,2,3}
Verbosity level; 0=minimal output, 1=normal output,
2=verbose output, 3=very verbose output
--settings SETTINGS The Python path to a settings module, e.g.
"myproject.settings.main". If this isn't provided, the
DJANGO_SETTINGS_MODULE environment variable will be
used.
--pythonpath PYTHONPATH
A directory to add to the Python path, e.g.
"/home/djangoprojects/myproject".
--traceback Raise on CommandError exceptions
--no-color Don't colorize the command output.
-
$ python manage.py crawler
で、実行する
all Topic=<QuerySet [<Topic: テスト記事1>]>
バージョン??
ヘルプで出るように、$ python manage.py crawler --version
でバージョンが表示されますが、何も定義しないと、Djangoのバージョンが表示されるようです。
公式ドキュメント
カスタム django-admin コマンドに、独自引数を追加する
続きを書きました。カスタム django-admin コマンドに、独自引数を追加する