ایجاد دستور (کامند) برای بارگذاری خودکار Fixturesهای کل پروژه در جنگو Django
در پروژههای جنگو Django، هنگام توسعهی پروژه، معمولا نیاز داریم که دادههای اولیه (fixtures) را در دیتابیس یا بانک اطلاعاتی بارگذاری کنیم. این کار به ما کمک میکند که بدون ورود دستی دادهها، محیط توسعه را سریعتر برای استفاده آماده کنیم. در این نوشته، قصد داریم یک دستور مدیریت سفارشی یا کامند (Management Command) ایجاد کنیم که تمام فایلهای fixture را از اپلیکیشنهای مختلف پروژه بهصورت خودکار همه را یکجا بارگذاری کند.
ایجاد دستور (کامند) برای بارگذاری خودکار Fixturesهای کل پروژه در جنگو Django
ایجاد دستور مدیریت سفارشی برای بارگذاری خودکار Fixtures
ایجاد یک فایل Command در پروژه: درون یکی از اپلیکیشنهای خود، مسیر زیر را ایجاد کنید:
your_app/ │── management/ │ ├── commands/ │ │ ├── __init__.py │ │ ├── load_all_fixtures.py <-- فایل جدید ما
در فایل load_all_fixtures.py، کد زیر را قرار دهید:
import os
from django.conf import settings
from django.core.management import call_command
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "Loads all fixtures automatically in dependency order"
def handle(self, *args, **options):
APP_MODE = settings.APP_MODE
if APP_MODE != "development":
self.stdout.write(
self.style.WARNING("This command is intended for development mode.")
)
return
local_apps = getattr(settings, "LOCAL_APPS", [])
if not local_apps:
self.stdout.write(self.style.ERROR("No LOCAL_APPS found in settings.py."))
return
fixtures_map = {}
for app_label in local_apps:
fixtures_dir = os.path.join(app_label.replace(".", "/"), "fixtures")
if os.path.exists(fixtures_dir):
fixtures = [
os.path.join(fixtures_dir, f)
for f in os.listdir(fixtures_dir)
if f.endswith(".json")
]
fixtures_map[app_label] = fixtures
if not fixtures_map:
self.stdout.write(self.style.WARNING("No fixtures found in any app."))
return
loaded_fixtures = set()
def load_fixture(fixture_path):
try:
self.stdout.write(f"Loading {fixture_path}")
call_command("loaddata", fixture_path)
loaded_fixtures.add(fixture_path)
return True
except Exception as e:
self.stdout.write(
self.style.WARNING(
f"Retrying later: {fixture_path} due to error: {e}"
)
)
return False
all_fixtures = [fp for fixtures in fixtures_map.values() for fp in fixtures]
while all_fixtures:
remaining_fixtures = []
for fixture_path in all_fixtures:
if not load_fixture(fixture_path):
remaining_fixtures.append(fixture_path)
if len(remaining_fixtures) == len(all_fixtures):
break
all_fixtures = remaining_fixtures
if all_fixtures:
self.stdout.write(
self.style.ERROR(
"The following fixtures could not be loaded due to errors:"
)
)
for fixture_path in all_fixtures:
self.stdout.write(self.style.ERROR(f" - {fixture_path}"))
else:
self.stdout.write(self.style.SUCCESS("All fixtures loaded successfully."))
توضیح عملکرد کد
این دستور چه کار میکند؟
- بررسی میکند که APP_MODE در تنظیمات پروژه برابر development باشد. اگر نباشد، دستور اجرا نخواهد شد.
- لیست اپلیکیشنهای محلی (LOCAL_APPS) را از فایل تنظیمات (settings.py) دریافت میکند.
- در هر اپلیکیشن، پوشه fixtures را جستجو میکند و فایلهای .json را پیدا میکند.
- تلاش میکند تا تمام fixtures پروژه را بارگذاری کند.
- اگر بارگذاری یک فایل به خطا بخورد، آن را در انتها دوباره تلاش میکند.
- در نهایت، اگر برخی از فایلها بارگذاری نشوند، لیست آنها را نمایش میدهد.
استفاده از این دستور در پروژه: برای اجرای این دستور، کافی است در ترمینال خود دستور زیر را اجرا کنید:
python manage.py load_all_fixtures
اگر همه چیز درست باشد، خروجی مشابه زیر خواهید دید:
Loading my_app/fixtures/sample_data.json
All fixtures loaded successfully.
اگر برخی از فایلها خطا داشته باشند، به شما اطلاع داده خواهد شد تا مشکل را بررسی کنید.
این دستور به شما کمک میکند که دادههای اولیه را در محیط توسعه بهراحتی بارگذاری کنید. همچنین، در صورت بروز خطا، آن را مدیریت کرده و تلاش مجدد انجام میدهد. با استفاده از این روش، دیگر نیازی نیست که هر بار به صورت دستی loaddata را برای هر اپلیکیشن اجرا کنید!


















میشه این دستور رو با cron یا زمان بندی اجرا کرد؟
بله امکانپذیراست.
وقتی فایل fixture ناقص باشه، دستور خودش retry می کنه؟
بله سعی میکنه مجدد اجرا کنه.
میشه ترتیب بارگذاری فایلها رو مشخص کرد؟
بله میتوانید اینکار را با کمی تغییر در کد کنید.
این دستور فقط برای محیط development کار میکنه؟
بله تفاوتی به محیط ندارد و این دستور قابل اجرا است.
اگر یکی از fixtures مشکل داشته باشه، کل فرآیند متوقف میشه؟
سعی میکنه تست کنه اگر حل شد که هیچی اگر نه باقی موارد رو اجرا میکنه.