
لقد مرت عدة أسابيع على الإصدار الرسمي للنسخة 3 من جانغو. لقد عملت مع هذا الإصدار حتى قبل نشر البيان الرسمي ، وللأسف ، لاحظت أن تطور Django تباطأ بشكل ملحوظ. يختلف الإصدار 1.3 عن 1.7 في بعض الأحيان ، ولكن الإصدار 3 يحتوي على تغييرات تجميلية على الفرع 2 وليس أكثر.
بدأ مشروع winePad الخاص بي مع الإصدار 1.3 من Django ، وقد أعاد تعريف 12٪ من الشفرة الداخلية لـ Django.
عند الاطلاع على الكود الخاص بالإصدار الجديد ، أفهم أن التعديلات التي أجريتها أنا أو زملائي أثناء العمل مع الإصدارات السابقة ستذهب إلى أبعد من ذلك. وبالنظر إلى خريطة الطريق والتغييرات البطيئة في المستودع الرسمي ، لا يتعين عليك انتظار تصحيح الأخطاء في الإصدارات المستقبلية.
هذا ما أريد أن أتحدث عن العمل على الأخطاء:
الحصول على الطريقة
قليل من الناس يدركون أن هناك خطأ في طريقة الحصول على django القياسية منذ البداية. يجب أن تقوم طريقة get بإرجاع كائن واحد إليك ، أو تحذير من العثور على عدة كائنات ، أو الإبلاغ عن عدم وجود كائنات.
1 def get(self, *args, **kwargs): 2 clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs) 3 if self.query.can_filter() and not self.query.distinct_fields: 4 clone = clone.order_by() 5 limit = None 6 if not clone.query.select_for_update or connections[clone.db].features.supports_select_for_update_with_limit: 7 limit = MAX_GET_RESULTS 8 clone.query.set_limits(high=limit) 9 num = len(clone) 10 if num == 1: 11 return clone._result_cache[0] 12 if not num: 13 raise self.model.DoesNotExist() 14 raise self.model.MultipleObjectsReturned()
يستقبل السطر 9 البيانات على جميع السجلات المحددة في مجموعة Queryset وترجمتها إلى مجموعة من الكائنات. هناك تحذير حول هذا في الوثائق.
قبل الإصدار 3 ، لم يكن هناك حد لعدد الكائنات المطلوبة. هذا يعني تلقي جميع البيانات تمامًا وتحويلها إلى كائنات ، قبل إعطاء تحذير بوجود الكثير من الكائنات.
نتيجة لذلك ، يمكنك الحصول على عدة ملايين من الكائنات في الذاكرة ، فقط لمعرفة أنه تم العثور على أكثر من كائن. الآن هناك خطوط 5،7،8. والآن يمكنك بفخر الحصول على MAX_GET_RESULTS = 21 كائنًا فقط قبل أن تعرف أن هناك أكثر من كائن واحد.
مع "__init__" الثقيلة ، سيكون التأخير كبيرًا. كيفية العلاج:
تجاوز MAX_GET_RESULTS في django.db.models.query.py
تجاوز GET أو قبل الاتصال باستخدام GET:
vars(queryset.query).update({'high_mark':2, 'low_mark':0}) queryset.query.set_limits(0,2)
__Init__ طريقة نماذج جانغو
الإعلان الموجود في رمز الأسلوب المدمج __init__ غير واضح تمامًا
_setattr=setattr
هذا على الأرجح من أجل التصلب الكاذب للرمز عن طريق نقل مرجع الوظيفة إلى القاموس المحلي ، ولكن هذا لا يعني ذلك. هناك العديد من المشاكل:
1. إذا مررت سمة إضافية = أزواج القيمة في نموذج __init__ ، فستحصل على "وسيطة للكلمة غير متوقعة".
في هذه الحالة ، أقترح عدم تحميل أسلوب __init__ ، ولكن لإضافة سمات بعد التهيئة:
obj = MyClass() vars(obj).update({'attr':val, 'attr2':val2 ...})
2. أضاف Django الجديد القدرة على إعادة تعريف الواصفات في أي مجال من مجالات النموذج (Field.descriptor_class). ولكن لا يعرف واصف واحد ما إذا كان الكائن مهيأ أم لا. يعد هذا ضروريًا ، على سبيل المثال ، إذا كان الواصف سيستخدم البيانات من الكائنات المرتبطة مسبقًا والتي ستظهر فقط بعد تهيئة الكائن الرئيسي.
لا أرغب في استخدام إشارة نهاية التهيئة ، لأنه يمكن أن يكون هناك الكثير من المشتركين.
في هذه الحالة ، لم أجد أي شيء أكثر ذكاءً من تجاوز __init__ وإضافة سمة لإنهاء التهيئة.
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._end_init = True
مجموعات طلبات البحث
تمت إزالة EmptyQuerySet / DateQuerySet الثابت ، إنه جيد بالفعل. ومع ذلك ، فإن الوضع مع queryset كمدير أنا لا أحب أيديولوجية.
إذا كنت تريد تجاوز فئة QuerySet التي أنشأها المديرون ، فأنا أضيف السمة _queryset_class
class MyManager(models.Manager): _queryset_class = MyQuerySet
الاهتمام ، بالنسبة للإصدارات الأقدم لا يعمل هذا ، على سبيل المثال ، يمكنك القيام بذلك:
class MyManager(models.Manager): def get_query_set(self): response = super(MyManager, self).get_query_set() response.__class__ = MyQuerySet return response
لوحة إدارة inlineFormset
هناك العديد من المشاكل:
1. لا يمكن عرض سجلات inlineFormset القياسية التي ليس لها اتصال مباشر بكائن النموذج الرئيسي. على سبيل المثال: نموذج لتحرير أسعار المنتجات. في الوسط يكمن شكل Tabularinline الإحصائي المرجعي لأسعار شراء الجملة للسلع "المماثلة".
يتم حلها عن طريق تخطي أسلوب نموذج get_formset المضمن وإنشاء MyFormSet الخاص بك الموروثة من BaseInlineFormSet
def get_formset(self, request, obj=None, **kwargs): kwargs['formset'] = MyFormSet super().get_formset(request, obj, **kwargs) class MyFormSet(BaseInlineFormSet): pass
2. إذا كنت تقوم بتحرير كائن باستخدام مجموعة مضمنة في لوحة المشرف ، وفي الوقت الحالي ، يقوم شخص ما بحذف أحد سجلات الكائن داخل مجموعة المعلومات المضمنة من خلال آلية أخرى ، ستتلقى خطأ ولن تتمكن من حفظ الكائن. فقط من خلال لصق kopy في نافذة متصفح جديدة.
لقد وجدت حل واحد فقط حتى الآن - لا تستخدم inlineformset.
لوحة الادارة
تعد "الميزة القاتلة" في جانغو ، أكبر صبار للمشروع:
1. يكون الإجراء "حذف الكائنات" في مسؤولي النماذج مرئيًا بشكل افتراضي ، ولا يهم ما إذا كان لدى المستخدم حقوق للحذف أم لا.
يتم حلها عن طريق تعطيل هذا الإجراء بشكل افتراضي:
admin.site.disable_action('delete_selected')
2. لن يكون إنشاء حقوق مستخدم إضافية من لوحة المسؤول ممكنًا حتى تقوم بتمكين مسؤول النموذج أذونات:
from django.contrib.auth.models import Permission class PermissionsAdmin(admin.ModelAdmin): search_fields = ('name', 'codename','content_type__app_label', 'content_type__model') list_display = ('name', 'codename',) actions = None admin.site.register(Permission, PermissionsAdmin)
3. للأسف ، الحق في الوصول إلى كائنات معينة فقط في جانغو غير موجود.
يمكن حل هذا عن طريق كتابة إدخال إلى djangoAdminLog مع علم خاص.
ثم تحقق من العلم:
user.logentry_set.filter(action_flag=ENABLED, .....).exists()
4. إذا قمت بإنشاء إجراءات المسؤول كما هو موضح في الوثائق ، تذكر أنه لم يتم تسجيلها تلقائيًا في djangoAdminLog.
5. عيب آخر في هذا الجزء من الوثائق هو أن جميع الأمثلة موجودة فقط في الوظائف. ولكن ماذا عن GCBV؟ في مشاريعي ، يتم نقل جميع تصرفات مسؤولي النماذج إلى GCBV.
مستودع.اتصال العمل هو المعيار:
class MyAdmin(admin.ModelAdmin): actions = (MyActionBasedOnActionView.as_view(),)
ContentType - نموذج تسجيل django
50 ٪ عبقرية / 50 ٪ بلادة.
لا يمكن لأي من النماذج الوصول إلى سجل النموذج الافتراضي.
في مشاريعنا ، يتم حلها عن طريق إضافة مزيج إلى جميع الفئات:
from django.contrib.contenttypes.models import ContentType class ExportMixin(object): @classmethod def ct(cls): if not hasattr(cls, '_ct'): cls._ct, create = ContentType.objects.get_or_create(**cls.get_app_model_dict()) if create: cls._ct.name = cls._ct.model._meta.verbose_name cls._ct.save() return cls._ct @classmethod def get_model_name(cls): if not hasattr(cls, '_model_name'): cls._model_name = cls.__name__.lower() return cls._model_name @classmethod def get_app_name(cls): if not hasattr(cls, '_app_name'): cls._app_name = cls._meta.app_label.lower() return cls._app_name @classmethod def get_app_model_dict(cls): if not hasattr(cls, '_format_kwargs'): cls._format_kwargs = {'app_label': cls.get_app_name(), 'model': cls.get_model_name()} return cls._format_kwargs
الآن يمكننا استدعاء obj.ct () إذا لزم الأمر.
UserModel
ظهرت القدرة على تجاوز طراز المستخدم في الإصدار 1.5.
ولكن بالنسبة للإصدار 3 ، لم يتم إصلاح النموذج = مستخدم في UserCreationForm / UserChangeForm القياسي.
تم حلها:
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import get_user_model class MyUserCreationForm(UserCreationForm): class Meta: model= get_user_model()
نظام الترجمة
يتم تمييز العلامات المرئية للمستخدم
{% trans %}
أو في رمز من خلال
gettext_lazy
ومع ذلك ، لا توجد إدارة لهذه الموارد في لوحة الإدارة. عموما.
هناك حلول خارجية ، كلها تعمل بطريقة ما.
على سبيل المثال ، يفقد Rosetta النصوص بشكل منهجي ، وتعمل الواجهة عربات التي تجرها الدواب. لا يوجد التحقق من حقوق الوصول إلى الترجمات في أي مكان. هناك حاجة إلى makemessages / compilemessages للعمل ...
في winePad ، تم إعادة تعريف العلامات العابرة و blocktrans و gettext_lazy وبدأنا في استلام النصوص من ذاكرة التخزين المؤقت. إذا لم يكن هناك ذاكرة تخزين مؤقت ، فإن الطلب المخبأ من قاعدة get_or_create أنقذنا أيضًا من رسائل makemessages.
موضوع تعدد اللغات معقد بشكل عام. الحل المدمج في Django يعمل فقط للنصوص الثابتة. ولكن لا تزال هناك حاجة لترجمة هذه النماذج. حاولت بطريقتي الخاصة حل مشكلة ترجمة النصوص الديناميكية في مشروع
django-TOF ، حيث قمت بدمج قدرات الترجمة النموذجية و Parler / Hvad. ربما شخص ما سوف تكون مهتمة في النظر.
في الوقت الحالي ، سوف أتوقف عن السرد ، حيث إن مقالة إصلاح أخطاء دانغو يمكن أن تتحول بسهولة إلى مقطع طويل.
فضلاً أخبرني كيف تقوم بتحسين جانغو الخاص بك. إذا كان هناك استمرار ، أقوم بتنظيم الأفكار التي نشأت.
سكرتير خاص تتم كتابة بعض الرموز في التدوين القديم ، وآمل أن أفهم ، لم يتم العثور دائما على الوقت أو الموظفين لإعادة بناء المساكن.