كما تعلمون بالفعل أنا أحب الكتابة ثابت اختياري. الشيء هو أنه في بعض الأحيان ليست اختيارية ، ولكن من المستحيل. لأن لدينا الكثير من المشاريع الكبيرة الغير نمطية في النظام البيئي لبيثون.
كان دجانغو وجانغو ريست فريم اثنين منهم. كانت. لأنه الآن يمكن كتابتها! اسمحوا لي أن أعرض Typed Django منظمة و بذرة ل django
و drf
.
سيكون هذا البرنامج التعليمي موجزة والبدء في دليل.
مجد
أريد أن أقول "شكراً" كبيرة لمكرنيكوف لقيادته المشروع ولجميع المساهمين الذين جعلوا هذا ممكنًا. أنت كل شيء رائع!
TLDR
في هذه المقالة ، أعرض كيف تعمل الأنواع مع django
و drf
. يمكنك إلقاء نظرة على النتيجة هنا .
ويمكنك أيضًا استخدام wemake-django-template
لبدء مشاريعك الجديدة بكل شيء تم تكوينه بالفعل. سيبدو تمامًا كمثال على المشروع.
الابتداء
في هذا البرنامج التعليمي الصغير ، سأريك العديد من ميزات django-stubs
و djangorestframework-stubs
في العمل. آمل أن يقنعك ذلك بأن قيام شخص ما بمراجعة الأمور بعدك أمر جيد.
يمكنك دائمًا الرجوع إلى الوثائق الأصلية. وتغطي جميع الخطوات أيضا هناك.
للبدء ، سنحتاج إلى مشروع جديد وبيئة افتراضية نظيفة ، حتى نتمكن من تثبيت تبعياتنا:
pip install django django-stubs mypy
ثم سنحتاج إلى تكوين mypy
بشكل صحيح. يمكن تقسيمها إلى خطوتين. أولاً ، نقوم بتكوين mypy
نفسه:
# setup.cfg [mypy] # The mypy configurations: https://mypy.readthedocs.io/en/latest/config_file.html python_version = 3.7 check_untyped_defs = True disallow_any_generics = True disallow_untyped_calls = True disallow_untyped_decorators = True ignore_errors = False ignore_missing_imports = True implicit_reexport = False strict_optional = True strict_equality = True no_implicit_optional = True warn_unused_ignores = True warn_redundant_casts = True warn_unused_configs = True warn_unreachable = True warn_no_return = True
ثم نقوم بتكوين البرنامج المساعد django-stubs
:
# setup.cfg [mypy] # Appending to `mypy` section: plugins = mypy_django_plugin.main [mypy.plugins.django-stubs] django_settings_module = server.settings
ماذا نفعل هنا؟
- نضيف
mypy
مخصصًا mypy
للمساعدة في تخمين مدقق الكتابة في بعض المواقف المعقدة الخاصة بـ Django (مثل النماذج ، queryset ، الإعدادات ، إلخ) - نضيف أيضًا تهيئة مخصصة لـ
django-stubs
إلى الإعدادات ، نستخدمها في Django. سوف تحتاج إلى استيراده.
النتيجة النهائية يمكن العثور عليها هنا .
لدينا الآن كل ما تم تثبيته وتكوينه. دعونا اكتب التحقق من الأشياء!
طرق فحص الكتابة
لنبدأ بكتابة طرق العرض نظرًا لأنه أسهل شيء بالنسبة لهذا المكون الإضافي.
إليكم وجهة نظرنا البسيطة المبنية على الوظيفة:
لنركض ونرى ما هي الأنواع التي يعرفها. لاحظ أننا قد نحتاج إلى تعديل PYTHONPATH
، حتى mypy
من استيراد مشروعنا:
» PYTHONPATH="$PYTHONPATH:$PWD" mypy server server/apps/main/views.py:14: note: Revealed type is 'def () -> builtins.bool' server/apps/main/views.py:15: note: Revealed type is 'django.contrib.auth.models.User'
دعنا نحاول كسر شيء:
كلا ، هناك خطأ مطبعي وسوف mypy
قبض عليه:
» PYTHONPATH="$PYTHONPATH:$PWD" mypy server server/apps/main/views.py:18: error: Argument 1 to "render" has incompatible type "Dict[str, Any]"; expected "HttpRequest"
إنه يعمل! حسنًا ، لكن هذا جميل تمامًا. دعنا نعقد مثالنا قليلاً وننشئ نموذجًا مخصصًا لإظهار كيف يمكننا كتابة النماذج و querysets.
نماذج typechecking و queryset
جانغو ORM هي ميزة القاتل. انها مرنة جدا وديناميكية. وهذا يعني أيضًا أنه من الصعب الكتابة. دعونا نرى بعض الميزات التي تغطيها بالفعل django-stubs
.
تعريف نموذجنا:
وتغطي كل مجال من مجالات هذا النموذج بواسطة django-stubs
. دعونا نرى ما هي أنواع كشفت:
» PYTHONPATH="$PYTHONPATH:$PWD" mypy server server/apps/main/models.py:21: note: Revealed type is 'builtins.int*' server/apps/main/models.py:22: note: Revealed type is 'django.contrib.auth.models.User*' server/apps/main/models.py:23: note: Revealed type is 'builtins.str*' server/apps/main/models.py:24: note: Revealed type is 'builtins.bool*' server/apps/main/models.py:25: note: Revealed type is 'datetime.datetime*'
كل شيء يبدو جيدا! يوفر django-stubs
mypy
مخصصًا mypy
لتحويل حقول النماذج إلى أنواع مثيل صحيحة. لهذا السبب يتم كشف جميع الأنواع بشكل صحيح.
الميزة الثانية الكبيرة في البرنامج المساعد django-stubs
هي أنه يمكننا كتابة QuerySet
:
وإليك كيف يمكن التحقق من ذلك:
reveal_type(published_posts().first())
يمكننا حتى .values()
باستخدام .values()
و .values_list()
. هذا البرنامج المساعد ذكي!
لقد QuerySet
صعوبات في شرح طرق إعادة QuerySet
لعدة سنوات. تعمل هذه الميزة على حل مشكلة كبيرة بالنسبة لي: لم يعد Iterable[BlogPost]
أو List[User]
. يمكنني الآن استخدام أنواع حقيقية.
Typechecking واجهات برمجة التطبيقات
لكن كتابة طرق العرض والنماذج والنماذج والأوامر وعناوين url والمشرف ليست هي كل ما لدينا. يحتوي TypedDjango أيضًا على نسخ djangorestframework
. دعونا تثبيت وتكوينه:
pip install djangorestframework djangorestframework-stubs
ويمكننا البدء في إنشاء مسلسلات:
المشاهدات:
وأجهزة التوجيه:
لا يبدو الأمر كما لو أن شيئًا ما قد تغير ، لكن كل ما بداخله كان مكتوبًا: الإعدادات ، والمتسلسلات ، ووجهات النظر ، وأجهزة التوجيه. سيتيح لك ذلك إضافة تدرجات بشكل متزايد إلى حيث تشتد الحاجة إليها.
دعنا نحاول تغيير queryset = BlogPost.objects.all()
إلى queryset = [1, 2, 3]
في آرائنا:
» PYTHONPATH="$PYTHONPATH:$PWD" mypy server server/apps/main/views.py:25: error: Incompatible types in assignment (expression has type "List[int]", base class "GenericAPIView" defined the type as "Optional[QuerySet[Any]]")
لا ، لن ينجح! إصلاح التعليمات البرمجية الخاصة بك!
استنتاج
كتابة واجهات الإطار أمر رائع. عندما يتم دمجها مع أدوات مثل returns
mappers
، فإنها ستسمح لكتابة منطق الأعمال الآمن للنوع والملفوف في واجهات إطار عمل مكتوبة. ولتقليل عدد الأخطاء في الطبقة بين هذين.
تتيح لك الكتابة الثابتة التدريجية الاختيارية أيضًا البدء بسرعة وإضافة أنواع فقط عندما يتم تثبيت واجهة برمجة التطبيقات (API) الخاصة بك أو الانتقال مع التطوير القائم على الأنواع من البداية.
ومع ذلك ، فإن django-stubs
و djangorestframework-stubs
من المشاريع الجديدة. لا يزال هناك الكثير من الأخطاء ، والميزات المخطط لها ، في عداد المفقودين المواصفات النوع. نرحب بكل مساهمة من المجتمع لجعل أدوات المطور في Python رائعة حقًا.
نشرت أصلا في مدونتي .