Jinja: من المستحيل التكرار على الكائن باستخدام عنصر "العناصر"

تم إنشاؤها على ٩ يناير ٢٠١٧  ·  10تعليقات  ·  مصدر: pallets/jinja

يقوم الخادم بإرجاع ملف JSON هذا:
{
"العناصر": [1،2،3]
...
}

ينتج عن محاولة تكرار "العناصر":
{٪ لـ el in data.items٪}
....
TypeError: الكائن "builtin_function_or_method" غير قابل للتكرار

يحدث أعلاه لأن بايثون ديكت لديها وظيفة مضمنة "العناصر ()".

كدرجة حرارة. لحل المشكلة ، قمت بتثبيت خطاف وأعدت تسمية المفاتيح في استجابة JSON من "العناصر" إلى "__items" ثم تمرير ذلك إلى Jinja2. في هذه المرحلة ، أقوم بتكرار غرامة السمة المعاد تسميتها:
{٪ لـ el في البيانات .__ items٪}

من الناحية المثالية ، يجب أن يتجاهل Jinja2 الدوال المضمنة في حلقة for-loop أو جملة if-statement ما لم يتم استدعاؤها على وجه التحديد باستخدام تدوين function ().

التعليق الأكثر فائدة

يمكنك استخدام {% for el in data['items'] %} لتحديد أولويات العنصر. هذا مغطى أيضًا في الوثائق. http://jinja.pocoo.org/docs/2.9/templates/#variables

ال 10 كومينتر

يمكنك استخدام {% for el in data['items'] %} لتحديد أولويات العنصر. هذا مغطى أيضًا في الوثائق. http://jinja.pocoo.org/docs/2.9/templates/#variables

ستفشل إذا لم تتضمن استجابة JSON أحيانًا "العناصر" (لنفترض أنها كانت سمة اختيارية للاستجابة). في هذه الحالة ، ستنتج {٪ for el in data ['items']٪} أيضًا:
TypeError: الكائن "builtin_function_or_method" غير قابل للتكرار

... حيث يتم تعريف العناصر دائمًا (كوظيفة مضمنة).

وهذا خطأ ، IMO. يجب ألا تتعارض البيانات ["العناصر"] أبدًا مع العناصر المضمنة. بعبارة أخرى ، إذا كنت تريد تكرار سمة "عناصر" اختيارية بشكل واضح ، فأنت مجبر على إعادة تسميتها. من الناحية المثالية ، لا ينبغي أن يكون هذا هو الحال.

لماذا لا تتضمن استجابة JSON عناصر؟ لست متأكدًا تمامًا من أنني أرى المشكلة هنا. من المؤكد أنك تعرف مسبقًا ما هي بياناتك. يمكنك أيضًا في القوالب التحقق من المفاتيح باستخدام عامل التشغيل in في القواميس بالفعل.

تغيير هذا السلوك غير وارد تمامًا لأن الآلاف من القوالب قد تتعطل إذا أزلنا دعم هذه السمة / العنصر.

لا أقترح إسقاط أي شيء ، فقط لجعله أكثر صرامة.

تكمن المشكلة اليوم في أنك عندما تستخدم تدوين البحث الصريح: data['items'] فإنه يجد وظيفة قاموس مضمنة ولا ينبغي أن تفعل ذلك . بايثون لا تفعل ذلك ، ولا يجب أن تفعل جينجا. إذا احتاج المرء إلى استدعاء المضمن (أو أي وظيفة لهذا الأمر) ، فلديك رمز الاستدعاء الخاص به: data.items()

لست متأكدًا مما إذا كان من الواضح جدًا وجود حالة خاصة dict.items هناك. خاصةً لأنه لا يزال يفشل بالنسبة للأنواع الشبيهة بالديكت المخصصة أو ربما حتى OrderedDict . أعتقد أنه من الأفضل foo['items'] في تلك الحالات. إنه ليس سلوكًا رائعًا للغاية ولكنه متسق.

وممكن "الإصلاح / الإختراق" فقط يمكنني أن أتخيل أن hancle هذا بطريقة أجمل والتحقق ما إذا كان يتم استخدام سمة واضحة (أي ليست استدعاء دالة) في التكرار وتحاول أعاد على شيء غير موجود iterable لكن للاستدعاء . في هذه الحالة ، من غير المرجح أن تؤدي تجربة العنصر إلى كسر أي كود موجود. ومع ذلك ، فإن تنفيذ مثل هذا السلوك في Jinja من المحتمل أن يكون فظيعًا للغاية ؛)

لماذا هذه حالة خاصة؟ أطلب من Jinja أن يتصرف تمامًا مثل Python. على وجه التحديد ، يجب أن ينتج عن foo ['items'] لا شيء إذا لم يكن هناك "عناصر" مفتاح أدخلها المستخدم. اليوم ، تعود Jinja إلى إيجاد الوظيفة المضمنة التي تحمل الاسم نفسه. لذلك ببساطة افعل ما تفعله بايثون:

>>> print {}.get('items')
None

بالمناسبة ، أعتقد أيضًا أنه يجب التعامل مع الترميز البديل "foo.items" جيدًا أيضًا ، نظرًا لأنك تحتاج إلى استخدام "()" لاستدعاء قابل للاستدعاء ، ولكن إذا كنت تحتاج إلى بعض التوافق مع الإصدارات السابقة لـ foo.items للعثور على أي منهما مفتاح أو استدعاء وظيفة تلقائيًا ، ثم أعتقد أن هذا سيء للغاية.

منطق Jinja لكل من ['x'] و .x هو هذا:

  • تحقق مما إذا كان العنصر / Attr (أيًا كان بناء الجملة الخاص بك في Python) موجودًا ، إذا كانت الإجابة بنعم ، استخدم ذلك
  • تحقق مما إذا كان السمة / العنصر ("عكس" ما سيفعله بناء الجملة في Python) موجودًا ، إذا كانت الإجابة بنعم ، استخدم ذلك
  • تفشل إذا لم تكن موجودة

لذلك يتحقق x.items من السمة وبما أن واحدة موجودة فإنها تستخدم ذلك. هذا المنطق يعمل بهذه الطريقة بغض النظر عن المسابقة. قد يتطلب تحسين هذا تغيير منطق البحث عن السمة بناءً على سياقها. وحتى مع ذلك ، قد يؤدي ذلك إلى مواقف محرجة مثل هذا الرمز الذي من شأنه أن يعمل:

{% for x in mydict.items %}

مقابل هذا الرمز الذي لن يعمل

{% set items = mydict.items %}
{% for x in items %}

وسيكون الاحتفاظ بمعالجة خاصة في هذه الحالة أمرًا مستحيلًا دون تتبع مصدر المتغير.

slisznia ، أنت تطلب بشكل أساسي من Jinja2 أن يغير نظام البحث عن السمات تمامًا والذي كان موجودًا منذ حوالي 7 سنوات في هذه المرحلة.

آه ، لم أشاهد حتى اقتراح foo['bar'] لا يقوم بالبحث عن سمة. هذه فكرة سيئة بالتأكيد! ما خطبك ببساطة باستخدام for item in data.get('items', []) ؟

ThiefMaster يعمل mydict.get('items', []) بالطبع ، ونشكرك على الإشارة إلى طريقة أخرى غير إعادة تسمية المفاتيح.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات