حدود 6 سال از شروع کار من با فریم ورک برنامه نویسی Django میگذرد و در تمام این سالها، سفارشیسازیهای شخصی زیادی در ساختار و سبک کدنویسی با Django انجام دادهام.
اکنون تصمیم گرفتهام که تمام این کارهایی که باید انجام داد و نباید انجام داد را به عنوان یک مربی، جمعبندی کنم تا بتوانم در آینده برای تدریس زبانهای برنامه نویسی از آنها استفاده کنم. همچنین این اطلاعات ممکن است برای دیگران مفید باشد.
تنظیمات Modular :
https://github.com/mrShahsafi/Edu/tree/master/djnagoForFun/djnagoForFun/settings
هنگامی که پروژه برنامه نویسی Django خود را توسعه میدهید، پس از نوشتن هر web-app جدید، متوجه خواهید شد که چیزهای زیادی در settings.py خود دارید و یافتن و مدیریت config هایتان هر روز سختتر از دیروز میشود.
همانطور که متوجه شدید، هنگامی که فرمان بسیار معروف manage.py در Django را فرامیخوانید، DJANGO_SETTINGS_MODULE را ایجاد کرده و PROJECT_NAME.settings را روی آن تنظیم میکنید.
کار که من در این بخش از برنامه نویسی Django انجام میدهم این است که settings.py را با init.py به یک module پایتون تبدیل میکنم.
هر پروژه حداقل دارای 2 محیط در حال اجرای مجزا است:
- محیط توسعه
- محیط تولید
و برخی از تنظیمات configs شما، در محیطهای مختلف مشابه هستند.
تا به حال میتوانیم سه فایل را در module تنظیمات خود قرار دهیم:
- base.py
- development.py
- production.py
همانطور که گفتم، base.py برای config هایی است که در محیطهای مختلف مشابه هستند.
:base.py
from pathlib import Path
import os # Do not delete this
# Your everywhere service name
SITE_NAME = ""
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv(
"DJANGO_KEY",
default=“”,
)
# Application definition
DEFAULT_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
THIRD_PARTY_APPS = []
CREATED_APPS = []
INSTALLED_APPS = DEFAULT_APPS + CREATED_APPS + THIRD_PARTY_APPS
MIDDLEWARE = []
ROOT_URLCONF =
TEMPLATES =
WSGI_APPLICATION =
AUTH_PASSWORD_VALIDATORS =
# Internationalization
…
# Static files (CSS, JavaScript, Images)
…
if not os.path.exists("logs"):
os.makedirs(os.path.join(BASE_DIR, "logs"))
خیلی جذاب بود، نه!؟ بیایید سراغ فایلهای دیگر برویم.
در development.py باید فقط development configs (پیکربندیهای توسعه) را وارد کنید.
development.py
from .base import *
# import socket # only if you haven't already imported this
DEBUG = True
ALLOWED_HOSTS = [
"localhost",
"127.0.0.1",
]
try:
from .local import *
except Exception:
pass
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
INSTALLED_APPS += [
"debug_toolbar",
# 'django_extensions'
]
MIDDLEWARE += [
"debug_toolbar.middleware.DebugToolbarMiddleware",
]
"""
These commented config will use \
when you are running the project on Docker.
"""
# hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
# INTERNAL_IPS = [ip[:-1] + "1" for ip in ips] + ["127.0.0.1", "10.0.2.2"]
INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
ممکن است متوجه فایل local.py شوید که در اینجا قرار دادهام. بعداً به آن خواهم پرداخت.
حالا بیایید نگاهی به config های تولید خود بیندازیم.
production.py
from .base import *
DEBUG = False
ALLOWED_HOSTS = [#YOUR_PRODUCTION_HOSTS_ADDRESSESS]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": os.getenv("DB_NAME", default="db"),
"USER": os.getenv("DB_USER", default="root"),
"PASSWORD": os.getenv("DB_PASS", default="root-password"),
"HOST": "postgres",
"PORT": "5432",
}
}
وقتی سه فایل خود را داریم، باید به نحوی آنها را در نقطه ورودی module تنظیمات مدیریت کنیم. منظورم این است که init.py: فایل اولیه (initializer file) در module شماست:
:init.py
from os import getenv
env = getenv("DJANGO_ENV", default="development")
if env == "production":
print("You Are in the Production Mode.")
from .porduction import *
elif env == "development":
print("Warning! You Are in the Development Mode.\nDo Not use in any server.")
from .development import *
خب، حالا وقت آن است که آن فایل مرموز local.py را توضیح دهیم! هر چیزی که فقط به تنظیمات local machine شما تعلق دارد، در آنجا قرار میگیرد. به عنوان مثال، config های مربوط به SMTP ایمیل شما، دیتابیس محلی شما و غیره. به یاد داشته باشید که local.py همیشه در .gitignore خواهد بود.
البته، Django معمولاً شامل module های شخص ثالث بیشتری مانند DRF ، Celery ، Allauth ، سرویسهای cache ، هدرهای CORS ، کانالها و Sentry است. اکنون همه چیز ساده است، شما یک فایل جداگانه برای هر یک از این module ها میسازید و آن را در انتهای فایل base.py خود فراخوانی میکنید. در اینجا من فقط DRF را توضیح میدهم تا شما الگو را یاد بگیرید.
base.py
# At the end of your base.py
try:
from .drf_settings import *
except Exception:
pass
:drf_settings.py
from datetime import timedelta
from .base import SITE_NAME
REST_FRAMEWORK = {
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PARSER_CLASSES": (
"rest_framework.parsers.JSONParser",
"rest_framework.parsers.MultiPartParser",
"rest_framework.parsers.FileUploadParser",
),
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
),
"DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",),
"DEFAULT_PAGINATION_CLASS": "core.pagination.CustomPagination",
"PAGE_SIZE": 9,
# "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.AcceptHeaderVersioning", # when we active versioning the swagger ui brakes!= ""
"TEST_REQUEST_DEFAULT_FORMAT": "json",
"EXCEPTION_HANDLER": "core.errors.custom_exception_handler",
}
برنامههای شخص ثالث Django که میتوانند در زمان شما به شدت صرفهجویی کنند:
Sentry
تراکنشها، ارورها و دیگر مسائل پروژه شما را مدیریت میکند و به صورت هفتگی به شما گزارش میدهد.
Django debug toolbar
برای توسعه، ابزارهای خوبی مانند SQL query time و سیگنالهای موجود را ارائه میدهد.
Django Chacheops
یک برنامه آسان و روان که از queryset caching خودکار یا دستی و invalidation خودکار رویدادهای مبتنی بر granular پشتیبانی میکند.
Django Admin Honeypot
اپلیکیشن برنامه نویسی Django که ابزارهایی را برای جلوگیری از اسپم شدن فرمهای خودکار ارائه میدهد.
Django Seed
Django Seed از کتابخانه جعلی برای تولید دادههای آموزشی برای مدلهای برنامه نویسی Django شما استفاده میکند. این برنامه به منظور پشتیبانی از نسخههای جدیدتر پایتون و Django از طریق django_faker ، “hard-forked” شده است.
Django Filter
Django Filter یک اپلیکیشن قابل استفاده مجدد برای برنامه نویسی Django است که به کاربران اجازه میدهد تا فیلتر QuerySet داینامیک را از پارامترهای URL اضافه کنند.
Django Allauth
مجموعهای یکپارچه از اپلیکیشنهای Django که به احراز هویت، ثبت نام، مدیریت حساب و همچنین احراز هویت حساب شخص ثالث (social) میپردازد. و بیشتر اوقات، نیازهای شما را برآورده میکند.
DRF Spectacular
دانلود اسکیمای OpenAPI 3.0 منطقی و انعطافپذیر برای شرایطی که از Django REST framework و نوشتن API استفاده میکنید.
Django Cities
مدلهای Place و دادههای Place در سرتاسر جهان برای برنامه نویسی Django .
همیشه یک TODO داشته باشید
https://github.com/mrShahsafi/Edu/blob/master/djnagoForFun/TODO.md
وقتی کارهای زیادی دارید که باید خیلی سریع و به درستی انجام شوند، نمیتوانید تمام کارهای خود را در سرویس task management و tod-os یادداشت کنید.
اکثر توسعهدهندگان tod-os خود را در codebase مینویسند و در بیشتر موارد فراموش میکنند که آنها را انجام دهند.
پس مطمئن شوید که یک todo.md یا هر چیز دیگری دارید که لیست کارهایی که باید انجام دهید (tod-os list) را در آن ذخیره میکنید.
# The project Todo List items
---
- [ ] un-done Task
- [x] done Task
---
## Models
## APIs
- [ ] django channels middleware for JwtAuth
## Others
## Bugs
## Emails
- [x] Forgot Password link
## Tests
- [ ] model tests for Advertisement
## NOTES
یکی دیگر از مزایای فایل tod-os این است که میتوانید تمام tod-os خود را فقط در یک فایل برای بعداً ذخیره کرده و آنها را به عنوان یک سند پروژه آرشیو کنید.
همیشه یک web-app اصلی در Django داشته باشید:
https://github.com/mrShahsafi/Edu/tree/master/djnagoForFun/core
شما همیشه برخی از مدلها، validation ها، normalizer ها، permission ها و چیزهای دیگر را خواهید داشت که میتوانید در تمام web app های آینده خود از آنها استفاده کنید.
من این web app رایج را core (هسته) مینامم.
شما میتوانید آن را هر چیزی که دوست دارید نامگذاری کنید.
برای منسجم شدن از Django web-app استفاده کنید
https://github.com/mrShahsafi/socialmedia
به همان اندازه که web-app های شما یک عمل اتمی انجام میدهند، در آینده فضای بیشتری برای نگهداری از آنها خواهید داشت.
برای مثال، فرآیند authentication/authorization نباید در برنامه کاربر باشد. آنها 2 مرحله متفاوت هستند و با جداسازی web-app های آنها به راحتی module آنها را با تغییرات بسیار کمی در پروژه جدید خود copy/paste خواهید کرد.
دستورات مدیریت سفارشی برنامه نویسی Django :
https://github.com/mrShahsafi/Winance/tree/main/wallet/management/commands
Django یک تاپیک بسیار مفید دارد: مدیریت سفارشی cmd. با دنبال کردن این دستوارالعملها، دستور سفارشی شما به این صورت خواهد بود:
python manage.py my_custom_command
به عنوان مثال، شاید بخواهید قبل از انجام یک عمل خاص، دستور fake_user را ایجاد کنید. یا وابستگیهای دستگاه خود را آزمایش کنید. به این ترتیب، تمام دستورات شما هم برای نوشتن و هم برای اجرا یک ساختار دارند. و باور کنید، زمانی که پروژه شما پیچیده میشود، این موضوع بسیار مهم است.
پیامهای سرویس خود را در یک فایل جداگانه ذخیره کنید
https://github.com/mrShahsafi/Edu/blob/master/djnagoForFun/core/responses/api_messages.py
وقتی یک error ایجاد میکنید، یا permission denied را برمیگردانید، پیامی برای نشان دادن خواهید داشت.
از hardcoding آنها در منطق خود دوری کنید.
تنها چیزی که نیاز دارید، فقط یک فایل است که شامل همه این پیامها به عنوان متغیر باشد.
دور زدن معانی!
https://github.com/mrShahsafi/Winance/blob/main/wallet/models/base.py
گاهی اوقات برخی از اقدامات واقعاً نیازی به انجام دادن ندارند.
به عنوان مثال، شما باید روزانه مقدار زیادی داده را از دیتابیس خود حذف کنید.
این یک تراکنش گران برای دیتابیس شما خواهد بود.
از مدل انتزاعی که حاوی ویژگی is_deleted با مقدار پیشفرض False است، استفاده کنید و سعی کنید تمام مدلهای دیگر خود را در برنامه نویسی Django از این مدل رایج inherit کنید.
تنها کاری که برای bulk delete باید انجام دهید، این است که پرچم is_deleted نمونههای خود را به True تبدیل کنید و مطمئن شوید که queryset های خود را با این موارد فیلتر میکنید:
qs = Model.objects.filter(is_deleted=Flase)
کاری که من در اینجا انجام دادم، یک مثال است. اما شما ایده را متوجه شدید.
فایلهای web-app ها را مدیریت کنید
در برنامه نویسی Django (و هر برنامه نویسی دیگری) همیشه تمام کدهای خود را فقط در یک فایل ننویسید.
اگر میبینید که .py شما بزرگتر از چیزی است که در یک یا دو اسکرول دیده شود، شما باید آن را به فایلهای جداگانه تبدیل کنید. به خصوص وقتی که صحبت از views.py به میان میآید.
وظیفه یک view فقط ارائه منطق به یک controller خاص است.
کاری که من انجام میدهم، این است که یک لایه جدید به نام logics (منطق) به view های خود اضافه میکنم.
فرض کنید یک view ثبت نام به نام RegistrationApi داریم، می توانید منطقهای ثبت نام را در auth.logics.registration_api_logic بنویسید و از آن در view خود استفاده کنید.
به View ها و Mixin های عمومی پایبند باشید:
توسعهدهندگان در برنامه نویسی Django فکر میکنند View ها و Mixin های عمومی برای مبتدیان هستند، زیرا در این صنعت به عنوان توسعهدهندگان backend رشد کردهاند.
خوب باید بگویم که این اصلاً درست نیست.
این قدرت برنامه نویسی Django است.
اگر نیاز دارید همه چیز را از ابتدا بنویسید، پس چرا اصلاً از Django استفاده میکنید ؟
همچنین هنگامی که از چیزی مانند DRF spectacular برای Documenting نماها (views) استفاده میکنید، و اگر از View های عمومی استفاده کنید، برای این نوع module ها بسیار آسانتر است که schema و View شما را sync کنند.
از Serializer ها استفاده کنید!
این مفهوم ممکن است برای شما کمی عجیب باشد، اما چند بار شده که به جای استفاده از یک Serializer ، از request.data استفاده کردهاید؟
مطمئنم گاهی این اتفاق میافتد.
به یاد داشته باشید که Serializer ها بهترین روش برای API view شما هستند. (از validating تا ایجاد).
و دوباره، وقتی از چیزی مانند DRF spectacular برای Documenting استفاده میکنید، برای این نوع module ها بسیار آسان است که schema شما را sync کنند.
و همچنین به یاد داشته باشید، هنگامی که تسکهای خود را به عنوان یک فرآیند اتمی break میکنید، نگهداری آنها در آینده بسیار آسان خواهد بود.
بنابراین اگر میخواهید از من بشنوید:
Serializer های خود را بر اساس هویت آنها جدا کنید
داشتن این سه Serializer در برنامه نویسی Django :
1- MyModelListSerializer
2- MyModelDetailSerializer
3- MyModelInputSerializer
بهتر از داشتن MyModelSerializer است.
Fixtures:
برنامه نویسی Django مفهوم Fixtures را برای ارائه دادههای اولیه برای مدلها معرفی کرد.
همیشه directory مربوط به fixtures را داشته باشید. این به شما کمک میکند تا تمام فایلها و دادههای ثابت خود را در مکان خاصی ذخیره کنید.
نتیجهگیری
امیدواریم از برنامه نویسی Django با این مفاهیم و ساختارها لذت ببرید.
با تشکر از اینکه تا اینجا با ما بودید!
Leave feedback about this