آنچه در این مقاله میخوانید
نحوه ایجاد دستورات مدیریتی جدید در Django
۲۴ تیر ۱۳۹۹
جنگو، ابزارها و دستورات خط فرمان گوناگون و زیادی را فراهم میکند که میتوان آنها را توسط django-admin.py
و یا manage.py
در هر پروژه، اجرا کرد. اما یک نکته مثبت این است که میتوانید دستورات خود را نیز به آنها اضافه کنید. این دستورات مدیریتی میتواند برای تعامل با برنامهتان از طریق خط فرمان، بسیار مناسب باشد، همچنین میتواند به عنوان واسطی برای اجرای corn job
ها نیز ظاهر شود. در این مقاله آموزشی نحوه ایجاد دستورات خودتان در جنگو را خواهید آموخت.
در ادامه خواهید خواند:
- آشنایی با دستورات خط فرمان در جنگو
- مثالهای پایهای
- مدیریت ورودیها
- استایلدهی
- Cron Job
- اطلاعات بیشتر
- جمع بندی

آشنایی با دستورات خط فرمان در جنگو
قبل از اینکه شروع کنیم، بیایید لحظاتی را صرف آشنایی با رابط خط فرمان جنگو کنیم. به احتمال زیاد با دستوراتی نظیر startproject
، runserver
و یا collectstatic
آشنا هستید. برای مشاهده تمام دستوراتی که میتوانید در یک پروژه جنگو ایجاد کنید، از دستور زیر در پروژهتان (در واقع جایی که فایل manage.py
قرار دارد) استفاده کنید:
python manage.py help
خروجی:
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver
میتوانیم دستورات خود را ایجاد کنیم و آنها را به این لیست اضافه کنیم. این کار را با ایجاد پوشه management/commands
در پوشه برنامه، همانند مثال زیر انجام میدهیم:
mysite/ <-- project directory
|-- core/ <-- app directory
| |-- management/
| | +-- commands/
| | +-- my_custom_command.py <-- module where command is going to live
| |-- migrations/
| | +-- __init__.py
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- models.py
| |-- tests.py
| +-- views.py
|-- mysite/
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
+-- manage.py
نام این فایل برای ایجاد دستور استفاده خواهد شد. برای مثال اگر اسم فایل my_custom_command.py
باشد، از طریق دستور زیر میتوانیم آن را اجرا کنیم:
python manage.py my_custom_command
بیایید سراغ مثالهای بعدی برویم.
هاست اختصاصی برای اجرای حرفهای اپلیکیشنهای Django، بدون پیچیدگیهای زیرساختی.
✅ پشتیبانی کامل از فریمورک Django✅ دیپلوی آسان با Git یا CLI✅ منابع اختصاصی، امنیت و عملکرد پایدار
خرید و راهاندازی هاست جنگو
مثالهای پایهای
مثال زیر، نمونهای از شیوه صحیح ایجاد یک دستور است:
management/commands/what_time_is_it.py
from django.core.management.base import BaseCommand
from django.utils import timezone
class Command(BaseCommand):
help = 'Displays current time'
def handle(self, *args, **kwargs):
time = timezone.now().strftime('%X')
self.stdout.write("It's now %s" % time)
اساسا دستورات مدیریتی جنگو با کلاسی به نام Command
، که از BaseCommand
ارثبری میکند، ساخته شدهاند. به این نکته توجه کنید که دستور را باید در داخل متد handle()
تعریف کنید.
در این مثال اسم فایل what_time_is_it.py
است، در نتیجه برای استفاده از آن، از دستور زیر استفاده میکنیم:
python manage.py what_time_is_it
خروجی:
It's now 18:35:31
شاید از خودتان بپرسید که تفاوت این روش با استفاده از یک اسکریپت ساده پایتونی چیست؟ و یا مزایای این روش چیست؟ مزیت اصلی این است که جنگو به طور کامل لود شده است و آماده استفاده است، این یعنی میتوانید مدلها را وارد کنید و کوئریهایی که نیاز دارید بر دیتابیس اجرا کنید را توسط ORM جنگو، بر روی دیتابیس پیاده کنید. در ضمن این اجازه را به شما میدهد که با تمام منابع پروژهتان نیز کار کنید.
مدیریت ورودیها
جنگو امکان استفاده از argparse (که جزو کتابخانههای استاندارد پایتون است) را فراهم میکند. برای مدیریت ورودیها در دستوراتمان، باید متدی با نام add_arguments
ایجاد کنیم.
ورودیهای اجباری
در مثال بعد دستوری را ایجاد میکنیم که به صورت رندوم کاربر میسازد (در واقع آبجکتی از کلاس User
بوجود میآورد و آن را در دیتابیس ذخیره میکند). این دستور یک ورودی اجباری، به نام total
میگیرد، که این ورودی مشخص کننده تعداد کاربرهایی است که میخواهیم ایجاد کنیم:
management/commands/create_users.py
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string
class Command(BaseCommand):
help = 'Create random users'
def add_arguments(self, parser):
parser.add_argument('total', type=int, help='Indicates the number of users to be created')
def handle(self, *args, **kwargs):
total = kwargs['total']
for i in range(total):
User.objects.create_user(username=get_random_string(), email='', password='123')
با روش زیر از این دستور استفاده میکنیم:
python manage.py create_users 10
هاست Python لیارا؛ اجرای سریع، امن و پایدار اپلیکیشنهای پایتون شما
✅ پشتیبانی کامل از فریمورکهای محبوب✅ دیپلوی آسان و سریع با Git یا CLI✅ منابع اختصاصی و امنیت بالا
خرید و راهاندازی هاست پایتون
ورودیهای اختیاری
ورودیهای اختیاری و نامگذاریشده میتوانند در هر ترتیبی به عنوان ورودی به دستور داده شوند. در مثال زیر یک ورودی با نام prefix
تعریف میکنیم، که از آن به عنوان پیشوندی برای ایجاد نامکاربری استفاده خواهیم کرد:
management/commands/create_users.py
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string
class Command(BaseCommand):
help = 'Create random users'
def add_arguments(self, parser):
parser.add_argument('total', type=int, help='Indicates the number of users to be created')
# Optional argument
parser.add_argument('-p', '--prefix', type=str, help='Define a username prefix', )
def handle(self, *args, **kwargs):
total = kwargs['total']
prefix = kwargs['prefix']
for i in range(total):
if prefix:
username = '{prefix}_{random_string}'.format(prefix=prefix, random_string=get_random_string())
else:
username = get_random_string()
User.objects.create_user(username=username, email='', password='123')
نحوه استفاده از این دستور:
python manage.py create_users 10 --prefix custom_user
و یا:
python manage.py create_users 10 -p custom_user
اگر prefix
تعیین شده باشد، نامکاربری مثل custom_user_oYwoxtt4vNHR
ایجاد خواهد شد، اما اگر prefix
تعیین نشود، نام کاربری oYwoxtt4vNHR
خواهد بود، یعنی مقدار رندومی که ایجاد شده است.
سوییچها
مدل دیگری از ورودیهای اختیاری، سوییچها و یا flag
ها هستند، که برای کنترل و تعیین مقادیر صحیح و غلط استفاده میشود. در نظر بگیرید که میخواهیم سوییچ --admin
را اضافه کنیم، تا بتوانیم به هنگام اجرای دستور، کاربری با دسترسی ادمین و یا کاربری با دسترسی معمولی، ایجاد کنیم:
management/commands/create_users.py
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string
class Command(BaseCommand):
help = 'Create random users'
def add_arguments(self, parser):
parser.add_argument('total', type=int, help='Indicates the number of users to be created')
parser.add_argument('-p', '--prefix', type=str, help='Define a username prefix')
parser.add_argument('-a', '--admin', action='store_true', help='Create an admin account')
def handle(self, *args, **kwargs):
total = kwargs['total']
prefix = kwargs['prefix']
admin = kwargs['admin']
for i in range(total):
if prefix:
username = '{prefix}_{random_string}'.format(prefix=prefix, random_string=get_random_string())
else:
username = get_random_string()
if admin:
User.objects.create_superuser(username=username, email='', password='123')
else:
User.objects.create_user(username=username, email='', password='123')
نحوه استفاده:
python manage.py create_users 2 --admin
و یا:
python manage.py create_users 2 -a
جنگو (Django) چیست؟
جنگو Django
لیستی دلخواه از ورودیها
بیایید دستور جدیدی با نام delete_users
ایجاد کنیم. در این دستور میتوانیم لیستی از id
کاربران را وارد کنیم، در نتیجه این دستور باید این کاربران را از دیتابیس حذف کند:
management/commands/delete_users.py
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Delete users'
def add_arguments(self, parser):
parser.add_argument('user_id', nargs='+', type=int, help='User ID')
def handle(self, *args, **kwargs):
users_ids = kwargs['user_id']
for user_id in users_ids:
try:
user = User.objects.get(pk=user_id)
user.delete()
self.stdout.write('User "%s (%s)" deleted with success!' % (user.username, user_id))
except User.DoesNotExist:
self.stdout.write('User with id "%s" does not exist.' % user_id)
نحوه استفاده:
python manage.py delete_users 1
خروجی:
User "SMl5ISqAsIS8 (1)" deleted with success!
همچنین میتوانیم لیستی از اعداد که با فاصله از هم جدا شدهاند را نیز به این دستور بدهیم تا کاربران با این id
های مشخص، توسط تنها یک دستور از دیتابیس حذف شوند:
python manage.py delete_users 1 2 3 4
خروجی:
User with id "1" does not exist.
User "9teHR4Y7Bz4q (2)" deleted with success!
User "ABdSgmBtfO2t (3)" deleted with success!
User "BsDxOO8Uxgvo (4)" deleted with success!
استایلدهی
میتوانیم مثالهای قبلی را با دادن رنگ مناسب به خروجی، بهبود ببخشیم:
management/commands/delete_users.py
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Delete users'
def add_arguments(self, parser):
parser.add_argument('user_id', nargs='+', type=int, help='User ID')
def handle(self, *args, **kwargs):
users_ids = kwargs['user_id']
for user_id in users_ids:
try:
user = User.objects.get(pk=user_id)
user.delete()
self.stdout.write(self.style.SUCCESS('User "%s (%s)" deleted with success!' % (user.username, user_id)))
except User.DoesNotExist:
self.stdout.write(self.style.WARNING('User with id "%s" does not exist.' % user_id))
نحوه استفاده همانند مثالهای قبل است، اما تفاوت تنها در خروجی است:
python manage.py delete_users 3 4 5 6
خروجی:

لیست زیر تمامی استایلهای موجود برای دستورات مدیریتی را نشان میدهد:
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Show all available styles'
def handle(self, *args, **kwargs):
self.stdout.write(self.style.ERROR('error - A major error.'))
self.stdout.write(self.style.NOTICE('notice - A minor error.'))
self.stdout.write(self.style.SUCCESS('success - A success.'))
self.stdout.write(self.style.WARNING('warning - A warning.'))
self.stdout.write(self.style.SQL_FIELD('sql_field - The name of a model field in SQL.'))
self.stdout.write(self.style.SQL_COLTYPE('sql_coltype - The type of a model field in SQL.'))
self.stdout.write(self.style.SQL_KEYWORD('sql_keyword - An SQL keyword.'))
self.stdout.write(self.style.SQL_TABLE('sql_table - The name of a model in SQL.'))
self.stdout.write(self.style.HTTP_INFO('http_info - A 1XX HTTP Informational server response.'))
self.stdout.write(self.style.HTTP_SUCCESS('http_success - A 2XX HTTP Success server response.'))
self.stdout.write(self.style.HTTP_NOT_MODIFIED('http_not_modified - A 304 HTTP Not Modified server response.'))
self.stdout.write(self.style.HTTP_REDIRECT('http_redirect - A 3XX HTTP Redirect server response other than 304.'))
self.stdout.write(self.style.HTTP_NOT_FOUND('http_not_found - A 404 HTTP Not Found server response.'))
self.stdout.write(self.style.HTTP_BAD_REQUEST('http_bad_request - A 4XX HTTP Bad Request server response other than 404.'))
self.stdout.write(self.style.HTTP_SERVER_ERROR('http_server_error - A 5XX HTTP Server Error response.'))
self.stdout.write(self.style.MIGRATE_HEADING('migrate_heading - A heading in a migrations management command.'))
self.stdout.write(self.style.MIGRATE_LABEL('migrate_label - A migration name.'))

Cron Job
اگر تسکی (task
) داشته باشید که بخواهید آن را به صورت دورهای اجرا کنید، مثل ایجاد گزارش در هر دوشنبه و یا یک scrapper
دارید که میخواهید برخی از دادهها را از چند صفحه وب مشخص، در هر ۱۰ دقیقه، ذخیره کند. میتوانید این کد را به عنوان یک دستور مدیریتی ایجاد کنید و آن را به فایل crontab
سرورتان اضافه کنید:
# m h dom mon dow command
0 4 * * * /home/mysite/venv/bin/python /home/mysite/mysite/manage.py my_custom_command
مثال بالا، دستور my_custom_command
را هر روز ساعت ۴ صبح، اجرا میکند.
اطلاعات بیشتر
مثالهایی که در این مقاله بررسی کردیم، برای شروع کار با دستورات سفارشی جنگو کافی هستند. اما اگر قصد دارید دستورات پیچیدهتری بنویسید—مانند دریافت ورودیهای مختلف، بررسی اعتبار آنها یا تعریف رفتارهای شرطی—نیاز دارید که با ماژول قدرتمند argparse
که جنگو از آن برای مدیریت آرگومانها و گزینههای خط فرمان استفاده میکند، بیشتر آشنا شوید.
به کمک argparse
میتوانید پارامترهای اختیاری و اجباری تعریف کنید، پیامهای راهنما اضافه کنید، مقدار پیشفرض تنظیم نمایید و انواع مختلفی از ورودیها را مدیریت کنید. این امکانات باعث میشوند دستورات شما انعطافپذیرتر، کاربرپسندتر و قابل استفاده در سناریوهای گستردهتری باشند.
همچنین توصیه میشود مستندات رسمی جنگو را در زمینه custom management commands مطالعه کنید. این مستندات حاوی مثالهای دقیقتری هستند و نکات مهمی مثل ساختار پروژه، ارثبری صحیح از کلاسهای BaseCommand
یا AppCommand
و روشهای برخورد با استثناها را توضیح میدهند.
در نهایت، با تمرین بیشتر و استفاده از مستندات، میتوانید دستورات سفارشی حرفهایتری بنویسید که بهخوبی با سایر اجزای پروژهی جنگوی شما هماهنگ باشند.
۸ پکیجی که باید در پروژههای جنگو استفاده کنید
۸ پکیج در پروژههای جنگو
جمع بندی
با استفاده از قابلیت ایجاد دستورات سفارشی در جنگو، میتوان فرآیندهای تکراری یا پیچیده را به شکل سادهتری اجرا کرد و آنها را به بخشی از ابزارهای خط فرمان پروژه تبدیل کرد. این ویژگی نهتنها توسعه و نگهداری پروژه را تسهیل میکند، بلکه امکان خودکارسازی بسیاری از کارهای رایج را نیز فراهم میسازد. با درک ساختار مدیریت دستورات و نحوه پیادهسازی آنها، میتوانید ابزارهایی دقیق و کاربردی برای پروژه خود بسازید و کنترل بیشتری روی محیط توسعه و اجرای برنامه داشته باشید.