فصل ۱: شروع درست — معماری، ساختار پروژه و Custom User

settings حرفه‌ای: .env، DEBUG، ALLOWED_HOSTS، زبان فارسی و منطقه‌ی زمانی

تنظیماتی که نباید در کد باشد

فایل settings.py در git می‌رود؛ پس SECRET_KEY، رمز پایگاه داده و کلید API پیامک نباید در آن نوشته شوند. قاعده‌ی ساده: هرچه بین لوکال و سرور فرق می‌کند یا محرمانه است، از متغیر محیطی خوانده شود. ساده‌ترین راه، فایل .env و کتابخانه‌ی python-dotenv است.

# .env  (در .gitignore)
DJANGO_SECRET_KEY=change-me-to-a-long-random-string
DJANGO_DEBUG=1
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
DB_NAME=carpet
DB_PASSWORD=
SMS_API_KEY=
# config/settings.py
import os
from pathlib import Path
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / ".env")

def env_bool(name, default="0"):
    return os.getenv(name, default).strip().lower() in {"1", "true", "yes", "on"}

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]      # نبودش = خطای فوری، نه کلید پیش‌فرض ناامن
DEBUG = env_bool("DJANGO_DEBUG")
ALLOWED_HOSTS = [h.strip() for h in os.getenv("DJANGO_ALLOWED_HOSTS", "").split(",") if h.strip()]

LANGUAGE_CODE = "fa"
TIME_ZONE = "Asia/Tehran"
USE_I18N = True
USE_TZ = True

AUTH_USER_MODEL = "accounts.User"   # درس ۵

برای ساختن یک کلید تصادفی امن:

python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"

معنای چند تنظیم کلیدی

تنظیمکارمقدار درست در سرور
DEBUGصفحه‌ی خطای کامل با متغیرها و تنظیمات؛ سرو خودکار staticهمیشه False
ALLOWED_HOSTSدامنه‌هایی که هدر Host آن‌ها پذیرفته می‌شود["example.ir", "www.example.ir"]
LANGUAGE_CODEزبان پیام‌های جنگو، ادمین و راست‌به‌چپ بودن آن"fa"
TIME_ZONEمنطقه‌ی زمانی نمایش و ورودی فرم‌ها"Asia/Tehran"
USE_TZذخیره‌ی زمان‌ها به UTC و aware بودن datetimeهاTrue

USE_TZ را خاموش نکنید

با USE_TZ = True جنگو همه‌ی زمان‌ها را در پایگاه داده به UTC ذخیره می‌کند و هنگام نمایش به وقت تهران برمی‌گرداند. برای «الان» همیشه django.utils.timezone.now() را به کار ببرید، نه datetime.now()؛ دومی زمان naive می‌دهد و هشدار «received a naive datetime» تولید می‌کند. برای «امروزِ تهران» هم timezone.localdate() درست است، نه date.today() که به ساعت سرور وابسته است.

نکته‌هایی که کمتر کسی می‌داند

  • bool(os.getenv("DJANGO_DEBUG")) برای رشته‌ی "False" هم True می‌دهد؛ هر رشته‌ی غیرخالی True است. همیشه مثل تابع env_bool بالا مقایسه کنید.
  • ایران از سال ۱۴۰۱ ساعت تابستانی ندارد. اگر روی ویندوز ساعت‌ها یک ساعت جابه‌جاست، بسته‌ی tzdata را در venv نصب یا به‌روز کنید؛ پایتون روی ویندوز پایگاه منطقه‌ی زمانی سیستمی ندارد.
  • برای عوض کردن SECRET_KEY بدون خارج شدن همه‌ی کاربران، کلید قدیمی را در SECRET_KEY_FALLBACKS بگذارید و بعد از چند هفته حذفش کنید.
  • با python manage.py diffsettings فقط تنظیماتی را می‌بینید که با پیش‌فرض جنگو فرق دارند؛ بهترین راه برای فهمیدن این‌که پروژه‌ی تحویل‌گرفته چه چیزی را عوض کرده است.
  • وقتی DEBUG=True و ALLOWED_HOSTS خالی است، جنگو خودش localhost و 127.0.0.1 را مجاز می‌داند؛ به همین دلیل خطای DisallowedHost معمولاً اولین بار روی سرور دیده می‌شود.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.