でカスタムコマンドを作成する方法
Djangoプロジェクトを開発するとき、特定のタスクを自動化する1つのスクリプトを書く必要があります.ここでは、私が私たちが実装を続ける前に私自身が適用したいくつかのユースケースがあります. 不完全なデータ列en masseを浄化すること. Aにおける複数スキーマの移行multitenant application
Djangoでこれらのタイプのコマンドを実行することができる2つの方法があります.通常のPythonスクリプトを作成し、実行して呼び出します
このポストのために、私はちょうど3つのデータベース表、ユーザー、カテゴリーとポストを持っているブログアプリでデモをします.
私はあなたがdjangoプロジェクトを快適に初期化していると仮定しました、しかし、あなたがそうでない場合には.this post あなたを助ける必要があります.
ソースコードはこちら👇🏽.
最初の例では、以下のスクリプトですべてのシステムユーザを一覧表示します
しかし、これはそうではありません.スクリプトがどのプロジェクトを適用するかをスクリプトが認識していないためです.つのマシンや仮想環境で複数のプロジェクトを持つことができます.スクリプトをコンテキストに与えることが重要です.
スクリプトを少し変更することでこれをします.
場合は、OSのモジュールに興味を持っているprevious post より多くの洞察を提供します.
インポートの順序が重要であり、そうでなければならないことに注意してください.
スクリプトをもう一度実行すると、すべてのユーザが端末に印刷されます👯♂️.
次の我々は実行してポストと呼ばれるアプリを初期化します
アプリは私たちのブログの投稿モデルを収容します.
< div >
この例では、コマンドラインからブログ投稿のインスタンスを作成します.スクリプトを初期化し、名前を付けます
<> P >
クラスをハイライト表示する
ここではブログ投稿のインスタンスを作成しています.どのように我々はForeignKey関係を処理する通知?関連するDBテーブルのオブジェクトインスタンスをそのフィールドに割り当てます.p >
< tt > Python CreateLand postを実行します.Pyを入力します.p >
前述のように、django管理コマンドは実行して実行されます
これにより、利用可能なコマンドの一覧が表示されます.p >
カスタム管理コマンドを登録するには、
私たちのケースでは、それはポスト\Management\コマンドp >
これを設定すると、コマンドフォルダでカスタムスクリプトを初期化できます.最初の例では、以前に作成したブログ投稿のフラグを出力するコマンドを書きます.p >
これを行うにはファイルを作成し、名前を付けます
<> P >
クラスをハイライト表示する
< tt > django管理コマンドはbasecommandから継承されるコマンドというクラスで構成されています.p >
引き数を扱うargparse . 方法
私たちの場合、関数はキーを割り当てられる引数を期待しています
< p >
上の例では、期待される引数の種類を位置引数と呼び、実行する関数に対して指定しなければなりませんbr/>
これを実行するには
オプションの引数としてもう一つの引数を適用することができます.名前が意味するように、これらの不足が関数の実行を妨げることはありませんp >
以下、実施例を示す.ファイルを初期化し、名前を付けます
<> P >
クラスをハイライト表示する
ここではブログ投稿のタイトルや内容を編集しますbr/>
これを実行するには
< p >あるいは
コンテンツを編集するにはbr/>
両方の引数を提供することができます両方のタイトルとコンテンツを編集したい
< OL > Django docs Simple is better than complex < OL >
それは私からです、質問があるならば、常に開いていますp >
python file_name.py
, そして、もう一つは、django管理コマンドを利用することです.これらは、呼び出しによって実行されますpython manage.py command_name
.このポストのために、私はちょうど3つのデータベース表、ユーザー、カテゴリーとポストを持っているブログアプリでデモをします.
私はあなたがdjangoプロジェクトを快適に初期化していると仮定しました、しかし、あなたがそうでない場合には.this post あなたを助ける必要があります.
ソースコードはこちら👇🏽.
ルイス香織 / ジャンゴコマンド
Djangoによるカスタムコマンド実装のデモ
通常のPythonスクリプトメソッド
最初の例では、以下のスクリプトですべてのシステムユーザを一覧表示します
from django.contrib.auth import get_user_model
User = get_user_model()
# retrieve all users
users = User.objects.all()
# loop through all users
for user in users:
print(f'user is {user.get_full_name()} and their username is {user.get_username()}')
スクリプトListHitユーザー名を指定できます.Pyとそれを実行しますpython list_users.py
これを実行すると、エラーが発生します.django.core.exceptions.ImproperlyConfigured: Requested setting AUTH_USER_MODEL, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
Djangoのプロジェクトディレクトリにいるので、スクリプトは問題なく実行されます.しかし、これはそうではありません.スクリプトがどのプロジェクトを適用するかをスクリプトが認識していないためです.つのマシンや仮想環境で複数のプロジェクトを持つことができます.スクリプトをコンテキストに与えることが重要です.
スクリプトを少し変更することでこれをします.
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projectname.settings')
import django
django.setup()
from django.contrib.auth import get_user_model
User = get_user_model()
users = User.objects.all()
for user in users:
print(f'user is {user.get_full_name()} and their username is {user.get_username()}')
ここでは、プロジェクトの設定を指定します.django.setup()
メソッド.このメソッドは、設定、ログ設定、およびアプリケーションのレジストリを設定します.要するに、スクリプトは我々のプロジェクト文脈を意識しています.場合は、OSのモジュールに興味を持っているprevious post より多くの洞察を提供します.
インポートの順序が重要であり、そうでなければならないことに注意してください.
スクリプトをもう一度実行すると、すべてのユーザが端末に印刷されます👯♂️.
次の我々は実行してポストと呼ばれるアプリを初期化します
django-admin startapp posts
.アプリは私たちのブログの投稿モデルを収容します.
< div >
この例では、コマンドラインからブログ投稿のインスタンスを作成します.スクリプトを初期化し、名前を付けます
create_post.py
<> P >
クラスをハイライト表示する
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commands.settings')
import django
django.setup()
from django.contrib.auth import get_user_model
from posts.models import Category, Post
User = get_user_model()
def select_category():
# retrieve categories. (You can create some examples from the django admin)
categories = Category.objects.all().order_by('created_at')
print('Please select a category for your post: ')
for category in categories:
print(f'{category.id}: {category}')
category_id = input()
category = Category.objects.get(id=category_id)
return category
def select_author():
# retrieve all users
users = User.objects.all()
print('Please select an author for your post: ')
for user in users:
print(f'{user.id}: {user}')
user_id = input()
user = User.objects.get(id=user_id)
return user
def create_post():
title = input("Title of your post: ")
content = input("Long post content: ")
category = select_category()
author = select_author()
Post(**locals()).save()
print('Post created successfully!')
if __name__ == "__main__":
create_post()
< div >ここではブログ投稿のインスタンスを作成しています.どのように我々はForeignKey関係を処理する通知?関連するDBテーブルのオブジェクトインスタンスをそのフィールドに割り当てます.p >
< tt > Python CreateLand postを実行します.Pyを入力します.p >
カスタムDjango管理コマンドメソッドの作成
前述のように、django管理コマンドは実行して実行されます
python manage.py command_name
これらの例はrunserver, migrate and collectstatic
. 利用可能なコマンドの一覧を取得するにはpython manage.py help
.これにより、利用可能なコマンドの一覧が表示されます.p >
カスタム管理コマンドを登録するには、
management\commands
あなたのDjangoアプリフォルダのディレクトリbr/>私たちのケースでは、それはポスト\Management\コマンドp >
これを設定すると、コマンドフォルダでカスタムスクリプトを初期化できます.最初の例では、以前に作成したブログ投稿のフラグを出力するコマンドを書きます.p >
これを行うにはファイルを作成し、名前を付けます
publish_post.py
<> P >
クラスをハイライト表示する
from django.core.management.base import BaseCommand, CommandError
from posts.models import Category, Post
class Command(BaseCommand):
help = 'Marks the specified blog post as published.'
# allows for command line args
def add_arguments(self, parser):
parser.add_argument('post_id', type=int)
def handle(self, *args, **options):
try:
post = Post.objects.get(id=options['post_id'])
except Post.DoesNotExist:
raise CommandError(f'Post with id {options["post_id"]} does not exist')
if post.published:
self.stdout.write(self.style.ERROR(f'Post: {post.title} was already published'))
else:
post.published = True
post.save()
self.stdout.write(self.style.SUCCESS(f'Post: {post.title} successfully published'))
< div >< tt > django管理コマンドはbasecommandから継承されるコマンドというクラスで構成されています.p >
引き数を扱うargparse . 方法
add_arguments
引数を受け取ることができます.p >私たちの場合、関数はキーを割り当てられる引数を期待しています
post_id
< p >
handle()
関数は入力を評価し、論理を実行するp >上の例では、期待される引数の種類を位置引数と呼び、実行する関数に対して指定しなければなりませんbr/>
これを実行するには
python manage.py publish_post 1 (or any post primary key)
オプションの引数としてもう一つの引数を適用することができます.名前が意味するように、これらの不足が関数の実行を妨げることはありませんp >
以下、実施例を示す.ファイルを初期化し、名前を付けます
edit_post.py
. 以下のコードを使用しますbr/><> P >
クラスをハイライト表示する
from django.core.management.base import BaseCommand, CommandError
from posts.models import Category, Post
class Command(BaseCommand):
help = 'Edits the specified blog post.'
def add_arguments(self, parser):
parser.add_argument('post_id', type=int)
# optional arguments
parser.add_argument('-t', '--title',type=str, help='Indicate new name of the blog post.')
parser.add_argument('-c', '--content',type=str, help='Indicate new blog post content.')
def handle(self, *args, **options):
title = options['title']
content = options['content']
try:
post = Post.objects.get(id=options['post_id'])
except Post.DoesNotExist:
raise CommandError(f'Post with id {options["post_id"]} does not exist')
if title or content:
if title:
old_title = post.title
post.title = title
post.save()
self.stdout.write(self.style.SUCCESS(f'Post: {old_title} has been update with a new title, {post.title}'))
if content:
post.content = content
post.save()
self.stdout.write(self.style.SUCCESS('Post: has been update with new text content.'))
else:
self.stdout.write(self.style.NOTICE('Post content remains the same as no arguments were given.'))
< div >ここではブログ投稿のタイトルや内容を編集しますbr/>
これを実行するには
python manage.py edit_post 2 -t "new title"
ちょうどタイトルを編集するには< p >あるいは
python manage.py edit_post 2 -c "new content"
コンテンツを編集するにはbr/>
両方の引数を提供することができます両方のタイトルとコンテンツを編集したい
python manage.py edit_post 2 -t "new title again" -c "new content again"
.余分の資源
< OL >
それは私からです、質問があるならば、常に開いていますp >
Reference
この問題について(でカスタムコマンドを作成する方法), 我々は、より多くの情報をここで見つけました https://dev.to/lewiskori/how-to-create-custom-commands-in-django-k9bテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol