okasha:templates

القوالب

تحتوي عكاشة على طريقة مرنة لعمل القوالب. حيث كل ما عليك هو تحديد الدالة التي ستسلم كائن بايثون (مصدره قد يكون قاعدة بيانات مثلا) مسؤولية تلك الدالة تحويل الكائن المستلم إلى صفحة ويب. يمكن استخدام كائن قابل للاستدعاء callable object أو نوع منه مكان الدالة حيث يتم إنشاء الكائن تلقائيا مرة واحدة عند تشغيل تطبيق الويب.

يتم تحديد الدالة عبر @expose

قوالب formatTemplate

هذه الدالة تحتاج تحديد ملف موجود في مجلد القوالب وتستلم قائمة من العناصر أو كائن من نوع قاموس dict. في الحالتين يوضع المعرف (الذي هو المفتاح في القاموس أو الإزاحة في القائمة) بين حاصرتين { }. إليك هذا المثال

  @expose(formatTemplate,["hello.html"])
  def hello(self, rq, *args):
    n=rq.q.getfirst('n','world').decode('utf-8')
    return {"name":n}

ويمكن أن تكون محتويات القالب كأي ملف HTML هكذا:

<html><body>
<h1>Hello, {name}!</h1>
<form name="MyForm">
Please enter name:
<input name="n" type="text" value="{name}"></input>
</form>
</body></html>

حيث سيتم تعويض قيم مفاتيح القاموس (وهي هنا name) مكان {name}

إن كنا أعدنا قائمة فإننا نستخدم الإزاحة هكذا {0} أي العنصر الأول و {1} أي العنصر الثاني.

توفر هذه الدالة الكثير من طرق التنسيق مثلا

<tt>{balance:.3f}</tt>

هذه الطريقة مفيدة جدا إلا أنه يعيبها

  • أنها لا تحتوي على حلقات تكرارية loops
  • مزعجة عندما يحتوي كود HTML على دوال جافاسكربت لأنه عليك تكرار الحاصرات

للمزيد انظر وثائق بايثون عن هذه الصيغة

قوالب percentTemplate

هذه الدالة تحتاج تحديد ملف موجود في مجلد القوالب وتستلم كائن من نوع قاموس dict مفاتيحه تستخدم كي يتم تعويض قيمها في القالب. إليك هذا المثال

  @expose(percentTemplate,["hello.html"])
  def hello(self, rq, *args):
    n=rq.q.getfirst('n','world').decode('utf-8')
    return {"n":n}

ويمكن أن تكون محتويات القالب كأي ملف HTML هكذا:

<html><body>
<h1>Hello, %(n)s!</h1>
<form name="MyForm">
Please enter name:
<input name="n" type="text" value="%(n)s"></input>
</form>
</body></html>

حيث سيتم تعويض قيم مفاتيح القاموس (وهي هنا n) مكان %(n)s والصيغة بكل بساطة تشبه printf وهي % ثم اسم المفتاح بين قوسين ثم رمز نوعه (غالبا s) ويجب الانتباه إلا أنه إن احتجت إلى % كما هي اكتب وهذه الطريقة كسابقتها يعيبها أنها لا تحتوي على حلقات تكرارية loops إلا أنها لا تكون مزعجة عندما يكون هناك داول javascript داخل كود html لكنها مزعجة عندما يكون هناك علامة % المستخدمة في سمات CSS حيث يجب أن تكتب

للمزيد انظر وثائق بايثون عن هذه الصيغة

قالب jsonDumps

في تطبيقات ويب 2.0 قد يلزمك إرسال بيانات عبر AJAX. إن أفضل طريقة للقيام بذلك هي عبر هيئة JSON وهي نص عبارة عن كود بلغة جافاسكربت يتم إرساله للطرف الآخر. يمنك تحويل أي كائن بايثوني إلى نص JSON عبر هذا القالب مهما كان معقدا يعني لو كان عندك منظومة array عناصرها قواميس dicts قيمها منظومة عناصرها منظومات …إلخ.

في هذا المثال فإن كود بايثون التالي يعيد منظومة بها 3 عناصر نصية

  @expose(jsonDumps)
  def array(self, rq, *args):
    return ["one","two","three"]

أما الكود التالي فيرسل قاموس (في جافاسكربت يصبح associated array) مفتاحاه الاسم name والوظيفة job

  @expose(jsonDumps)
  def array(self, rq, *args):
    return {"name":"Ahmad","job":"Manager"}

في جافاسكربت إن استلمت هذا الكائن تحت اسم d فإن القيم ستكون d.name و d.job

قوالب bottle المتقدمة

إن كنت بحاجة إلى جمل شرطية أو حلقات تكرارية أو تنفيذ أي كود بايثون أو حتى تسريع للقالب عبر عمل نسخة خبيئة مكونة من python byte code فإن هذا القالب هو ما تبحث عنه

<note tip>لا يحتاج هذا القالب أي اعتماديات خارجية ويوفر العديد من المزايا المتقدمة على بساطته</note>

في هذا القالب تستطيع وضع أي تعبير بايثوني (على أن يعيد نص أو عدة نصوص) بين حاصرتين مزدوجتين هكذا:

Hello, {{name}}!

هنا سيتم تعويض قيمة name بعد Hello. والتي قد تعطي شيء يشبه

Hello, Ali!

يمكن استخدام تعابير أعقد مثل

Hello, {{user.get_name() if user else "world"}}!

هذا التعبير البايثوني يعني إن كان الكائن user معرفا فإنه يستدعي الطريقة user.get_name وإلا فإنه يساوي الثابت “world”

كذلك يعمل على تخطي العلامة الخاصة ب html حتى تظهر بالشكل الصحيح. مثلا إن كانت القيمة مثلا <a> فإنه سيحوله إلى &lt;a&gt; حتى يظهر في HTML كما هو فإن كنت تريده أن يظهر دون تخطي ضع ! بعد فتح الحاصرتين.

Hello, {{!name}}!

يمكنك استخدام عبارات 'if' و 'elif' و 'else' و 'try' و 'except' و 'finally' و 'for' و 'while' و 'with' و 'def' و 'class' لكن على أن تبدأها ب % وأن لا يسبقها إلا مسافات وعلى أن تنهيها ب %end وذلك عوضا عن المسافات البادئة في بايثون مثلا يمكنك أن تعمل ما يشبه

<html>
 <head>
  <title>{{title}}</title>
 </head>
 <body>
  %if colors:
  %for c in colors:
    <p>I like <strong>{{c}}</strong> apple</p>
  %end
  %else:
    <p>no color is provided</p>
  %end
  <p>for more details on this template visit <a href="http://bottle.paws.de/docs/dev/stpl.html">Bottle Docs</a></p>
 </body>
</html>

كذلك يمكنك احتواء قالب آخر عبر %include ثم اسم الملف دون .tpl ثم إن شئت معاملات معرف = قيمة فاصلة معرف = قيمة وهكذا أو حتى ** ثم كائن dict

والأجمل من ذلك هو عمل قالب يحتوي عبارة %include دون أي معاملات في وسطه وفي ملف آخر يبدأ أو ينتهي بعملية %rebase متبوعة اسم ذاك القالب الأول (مع معاملات إن شئت) وعند استعمال الثاني سيتم معالجة القالب ثم حشره ناتجه في وسط الأول مكان كلمة %include

مثلا يكون عندك ملف layout.tpl يحتوي على كود html وكلمة %include في وسطه مثلا

<html>
<head>
  <title>{{title or 'No title'}}</title>
</head>
<body>
<div class="sidepane_block" style="width: 50%; float:right;">
{{sidepane()}}
</div>
<div class="content_block">
  %include
</div>
</body>
</html>

وفي ملف آخر نعمل

%def sidepane():
this will go on side box
%end
This is the page content: {{content}}
%rebase layout title='Content Title' sidepane=sidepane

علما أنه يمكن %rebase أكثر من مرة.

<note>هذا القالب مستعار من إطار الويب bottle وهو وفق رخصة MIT الحرة المتساهلة للمزيد من المعلومات راجع وثائق قالب bottle </note>

قوالب kid المتقدمة

إن كنت تريد قوالب تجمع بين بايثون و xml أو xhtml فعليك ب kid وهي حزمة متخصص في هذه الأشياء (اسمها في فيدورا هو python-kid).

<note important>إلى جانب حزمة python-okasha-kid التي هي جزء من عكاشة فإن هذا القالب بحاجة لحزمة خارجية وهي python-kid ولن يعمل إن لم تكن تلك الحزمة مثبتة.</note>

وتستخدم كما في المثال المرفق مع عكاشة test.py هكذا:

from okasha.kidTemplate import kidTemplate
  @expose(kidTemplate,["kidtest.kid"])
  def kidtmp(self, rq, *args):
    return {
      'h1':'this is how kid templates works',
      'ls':['apple','banana','orange','tomato']
      }

حيث هنا كما في percentTemplate نعيد قاموس لكن ليس بالضرورة أن تكون قيمه نصوصا حيث يمكن أن تكون القيم منظومة array كما في ls

أما ملف القالب kidtest.kid فهو xml يحتوي على تعويض قيم وحلقات بل وأكود بلغة بايثون

لاحظ كيف استدعينا بايثون كما نفعل مع php هكذا

<?python
import time
title = "A Kid Template"
?>

كذلك لاحظ كيف قمنا بتعويض القيم في هذا السطر

<title py:content="title">

وفي هذا السطر

<h1 py:content="h1">title goes here</h1>

والأجمل هو الحلقات التكرارية كما في

<ul>
    <li py:for="fruit in ls">I like ${fruit}s</li>
</ul>

سيقوم kid بتحويل الملف kidtest.kid إلى وحدة بايثونية مصنفة kidtest.pyc وسيتم عمل خبيئة منها cache مما يعني أنه عليك إعادة تشغيل التطبيق عند تعديل القالب.

للمزيد انظر وثائق kid

قوالب xslt

قالب xsltTemplate لتحويل أي كود xml إلى أي كود xml آخر مثل xhtml بواسطة ملف xsl

<note important>إلى جانب حزمة python-okasha-xslt التي هي جزء من عكاشة فإن هذا القالب بحاجة لحزمة خارجية وهي python-lxml ولن يعمل إن لم تكن تلك الحزمة مثبتة.</note>

سأكتب المزيد عنها

آخر تعديل:: 23 نيسان 2015 الساعة 00:21 (تحرير خارجي)