قم بتبسيط إعدادات Django باستخدام تلميحات الكتابة: برنامج تعليمي Pydantic
نشرت: 2022-07-22اعتادت مشاريع Django أن تحبطني لأنني كنت أفتقر إلى طريقة قوية وقابلة للتطوير لإضافة بيئات جديدة. من خلال الجمع بين تلميحات كتابة pydantic و Python ، قمت ببناء الأساس القوي الذي أحتاجه.
كما هو موضح في PEP 484 ، تدعم تلميحات الكتابة التحليل الثابت ، ولكن هذه التعليقات التوضيحية نفسها متاحة أيضًا في وقت التشغيل. تقدم حزم الطرف الثالث مثل pydantic فحص نوع وقت التشغيل الذي يستخدم هذه البيانات الوصفية الإضافية. يستخدم Pydantic تلميحات نوع Python للمساعدة في إدارة البيانات الوصفية للإعدادات وإجراء التحقق من صحة بيانات وقت التشغيل.
سيُظهر هذا البرنامج التعليمي pydantic الآثار الإيجابية بعيدة المدى لاستخدام إدارة إعدادات pydantic مع Django.
يلتزم التكوين الخاص بنا بأفضل الممارسات الموضحة على موقع تطبيق Twelve-Factor:
- تعريف التكوينات غير الثابتة والسرية كمتغيرات البيئة.
- في بيئات التطوير ، حدد متغيرات البيئة في ملف
.env
وأضف.env
إلى.gitignore
. - استخدم آليات موفر السحابة لتحديد متغيرات البيئة (السرية) لبيئات ضمان الجودة والتشغيل المرحلي والإنتاج.
- استخدم ملف
settings.py
واحدًا يقوم بتكوين نفسه من متغيرات البيئة. - استخدم pydantic لقراءة متغيرات البيئة والتحقق منها والتحقق من صحتها وتلبيتها على متغيرات Python التي تحدد تكوينات Django.
بدلاً من ذلك ، ينشئ بعض المطورين ملفات إعدادات متعددة ، مثل settings_dev.py
و settings_prod.py
. لسوء الحظ ، هذا النهج لا يتناسب بشكل جيد. يؤدي إلى تكرار الكود والارتباك والأخطاء التي يصعب العثور عليها وجهود صيانة أعلى.
باستخدام أفضل الممارسات المذكورة أعلاه ، فإن إضافة أي عدد من البيئات أمر سهل ومُحدد جيدًا ومقاوم للأخطاء. على الرغم من أنه يمكننا استكشاف تكوين بيئة أكثر تعقيدًا ، إلا أننا سنركز على اثنين من أجل الوضوح: التطوير والإنتاج.
كيف يبدو هذا في الممارسة؟
إدارة إعدادات Pydantic ومتغيرات البيئة
نركز الآن على مثال في كل من التطوير والإنتاج. نوضح كيف تقوم كل بيئة بتكوين إعداداتها بشكل مختلف وكيف يدعم pydantic كل منها.
يتطلب تطبيقنا النموذجي قاعدة بيانات مدعومة من Django ، لذلك نحتاج إلى تخزين سلسلة اتصال قاعدة البيانات. نقوم بنقل معلومات تكوين اتصال قاعدة البيانات إلى متغير بيئة ، DATABASE_URL
، باستخدام حزمة Python dj-database-url. يرجى ملاحظة أن هذا المتغير من النوع str
ويتم تنسيقه على النحو التالي:
postgres://{user}:{password}@{hostname}:{port}/{database-name} mysql://{user}:{password}@{hostname}:{port}/{database-name} oracle://{user}:{password}@{hostname}:{port}/{database-name} sqlite:///PATH
في بيئة التطوير الخاصة بنا ، يمكننا استخدام مثيل PostgreSQL مضمن في Docker لسهولة الاستخدام ، بينما في بيئة الإنتاج الخاصة بنا ، سنشير إلى خدمة قاعدة البيانات المتوفرة.
متغير آخر نريد تعريفه هو المتغير المنطقي DEBUG
. يجب عدم تشغيل علم DEBUG في Django مطلقًا في عملية نشر الإنتاج. الغرض منه هو الحصول على ملاحظات إضافية أثناء التطوير. على سبيل المثال ، في وضع التصحيح ، سيعرض Django صفحات خطأ مفصلة عند حدوث استثناء.
يمكن تحديد القيم المختلفة للتطوير والإنتاج على النحو التالي:
اسم المتغير | تطوير | إنتاج |
---|---|---|
DATABASE_URL | postgres://postgres:mypw@localhost:5432/mydb | postgres://foo1:foo2@foo3:5432/foo4 |
DEBUG | True | False |
نستخدم وحدة إدارة إعدادات pydantic لإدارة هذه المجموعات المختلفة من قيم متغيرات البيئة اعتمادًا على البيئة.
خطوات تحضيرية
لوضع هذا موضع التنفيذ ، نبدأ في تكوين بيئة التطوير الخاصة بنا عن طريق إنشاء ملف .env
واحد مع هذا المحتوى:
DATABASE_URL=postgres://postgres:mypw@localhost:5432/mydb DEBUG=True
بعد ذلك ، نضيف ملف .env
إلى ملف المشروع .gitignore
. يتجنب ملف .gitignore
حفظ المعلومات التي يحتمل أن تكون حساسة في التحكم بالمصادر.
في حين أن هذا النهج يعمل بشكل جيد في بيئة التطوير لدينا ، فإن مواصفات بيئة الإنتاج لدينا تستخدم آلية مختلفة. تملي أفضل ممارساتنا أن تستخدم متغيرات بيئة الإنتاج أسرار البيئة. على سبيل المثال ، في Heroku ، تسمى هذه الأسرار Config Vars ويتم تكوينها من خلال لوحة معلومات Heroku. يتم إتاحتها للتطبيق المنشور كمتغيرات البيئة:
بعد ذلك ، نحتاج إلى ضبط تكوين التطبيق لقراءة هذه القيم من أي من البيئتين تلقائيًا.
تكوين settings.py
Django.py
لنبدأ بمشروع Django جديد لتوفير الهيكل الأساسي لمثالنا. سقالة مشروع Django جديد بالأمر الطرفي التالي:
$ django-admin startproject mysite
لدينا الآن هيكل مشروع أساسي لمشروع mysite
. هيكل ملف المشروع على النحو التالي:
mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py
يحتوي ملف settings.py
على كود معياري يسمح لنا بإدارة تكوين التطبيق. يحتوي على العديد من الإعدادات الافتراضية المحددة مسبقًا والتي يجب علينا ضبطها وفقًا للبيئة ذات الصلة.
لإدارة إعدادات التطبيق هذه باستخدام متغيرات البيئة و pydantic ، أضف هذا الرمز إلى أعلى ملف settings.py
:
import os from pathlib import Path from pydantic import ( BaseSettings, PostgresDsn, EmailStr, HttpUrl, ) import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent class SettingsFromEnvironment(BaseSettings): """Defines environment variables with their types and optional defaults""" DATABASE_URL: PostgresDsn DEBUG: bool = False class Config: """Defines configuration for pydantic environment loading""" env_file = str(BASE_DIR / ".env") case_sensitive = True config = SettingsFromEnvironment() os.environ["DATABASE_URL"] = config.DATABASE_URL DATABASES = { "default": dj_database_url.config(conn_max_age=600, ssl_require=True) } DEBUG = config.DEBUG
يقوم هذا الرمز بما يلي:
- يعرّف فئة
SettingsFromEnvironment
FromEnvironment ، موروثة من فئةBaseSettings
الخاصة بـ pydantic. - يعرّف
DATABASE_URL
وDEBUG
، ويضبط نوعه والافتراضي الاختياري باستخدام تلميحات كتابة Python. - يحدد
Config
فئة يخبر pydantic بالبحث عن المتغيرات في ملف.env
إذا لم يكن موجودًا في متغيرات بيئة النظام. - يجسد فئة
Config
فيconfig
الكائن ؛ تصبح المتغيرات المرغوبة متاحة على هيئةconfig.DATABASE_URL
وconfig.DEBUG
. - يحدد
DATABASES
وDEBUG
متغيرات Django العادية من أعضاءconfig
هؤلاء.
يعمل نفس الكود في جميع البيئات ، ويتولى pydantic ما يلي:
- يبحث عن متغيرات البيئة
DATABASE_URL
وDEBUG
.- إذا تم تعريفها على أنها متغيرات البيئة ، كما هو الحال في الإنتاج ، فسوف تستخدم تلك المتغيرات.
- وإلا فإنه يسحب هذه القيم من ملف
.env
. - إذا لم يعثر على قيمة ، فسيقوم بما يلي:
- بالنسبة إلى
DATABASE_URL
، يظهر خطأ. - بالنسبة لـ
DEBUG
، فإنه يعين قيمة افتراضية لـFalse
.
- بالنسبة إلى
- إذا عثر على متغير بيئة ، فسوف يتحقق من أنواع الحقول ويعطي خطأً إذا كان أي منهما خاطئًا:
- بالنسبة إلى
DATABASE_URL
، يتحقق من أن نوع الحقل الخاص به هو عنوان URL بنمطPostgresDsn
. - بالنسبة لـ
DEBUG
، فإنه يتحقق من أن نوع الحقل الخاص به هو منطقي منطقي غير صارم.
- بالنسبة إلى
يرجى ملاحظة الإعداد الصريح لمتغير بيئة نظام التشغيل من قيمة التكوين لـ DATABASE_URL
. قد يبدو تعيين os.environ["DATABASE_URL"] = config.DATABASE_URL
لأنه تم تعريف DATABASE_URL
بالفعل على أنه متغير بيئة خارجي. ومع ذلك ، هذا يسمح pydantic لتحليل وفحص والتحقق من صحة هذا المتغير. إذا كان متغير البيئة DATABASE_URL
مفقودًا أو تم تنسيقه بشكل غير صحيح ، فسيعطي pydantic رسالة خطأ واضحة. عمليات التحقق من الأخطاء هذه لا تقدر بثمن حيث ينتقل التطبيق من التطوير إلى البيئات اللاحقة.
إذا لم يتم تعريف متغير ، فسيتم تعيين متغير افتراضي أو سيطالبك خطأ بتعريفه. أي مطالبات تم إنشاؤها بالتفصيل أيضًا نوع المتغير المطلوب. ومن المزايا الجانبية لهذه الفحوصات أن أعضاء الفريق الجدد ومهندسي DevOps يكتشفون بسهولة أكبر المتغيرات التي يجب تحديدها. يؤدي ذلك إلى تجنب المشكلات التي يصعب العثور عليها والتي تنتج عند تشغيل التطبيق بدون تحديد جميع المتغيرات.
هذا هو. يحتوي التطبيق الآن على تطبيق لإدارة الإعدادات يمكن صيانته باستخدام إصدار واحد من settings.py
. يكمن جمال هذا الأسلوب في أنه يسمح لنا بتحديد متغيرات البيئة الصحيحة في ملف .env
أو أي وسيلة أخرى مرغوبة متاحة من خلال بيئة الاستضافة الخاصة بنا.
المسار القابل للتطوير
لقد كنت أستخدم إدارة إعدادات Django مع كتابة وقت تشغيل pydantic في جميع مشاريع Django الخاصة بي. لقد وجدت أنه يؤدي إلى قواعد أكواد أصغر وأكثر قابلية للصيانة. كما أنه يوفر نهجًا منظمًا جيدًا وموثقًا ذاتيًا وقابلًا للتطوير لإضافة بيئات جديدة.
المقالة التالية في هذه السلسلة عبارة عن برنامج تعليمي خطوة بخطوة حول إنشاء تطبيق Django من البداية ، مع إدارة إعدادات pydantic ونشره في Heroku.
تعرب مدونة Toptal Engineering عن امتنانها لستيفن ديفيدسون لمراجعة عينات التعليمات البرمجية المقدمة في هذه المقالة.
أكدت نسخة سابقة من هذه المقالة على إصدار معين من Python. نظرًا لأن Python قد دعمت تلميحات الكتابة لعدة سنوات ، فقد قمنا بتعميم النص التمهيدي عن طريق إزالة مرجع الإصدار هذا.