Author Topic: The Big Three  (Read 882 times)

Ahmed Youssef

  • Helping Freak
  • Administrator
  • Active Member
  • *****
  • Posts: 242
    • View Profile
    • WWW
    • Email
The Big Three
« on: January 11, 2009, 03:45:14 PM »

The Big Three


هناك 3 اطارات تتصدر عالم بايثون فى الويب وهم Django و TurboGears و Pylons

Pylons هى اطار حديث نسبيا ويجمع افضل مافى العوالم python, ruby, perl واستفاد كثيرا من تجارب الإطارات السابقة
http://pylonshq.com/

Hello World: Pylons

Code: [Select]
striky@striky-desktop:~/workspace/pytut/src/nettut$ paster create -t pylons helloworld 
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/__init__.py:98: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/CherryPy-2.3.0-py2.5.egg/cherrypy/lib/profiler.py:54: UserWarning: Your installation of Python doesn't have a profile module. If you're on Debian, you can apt-get python2.4-profiler from non-free in a separate step. See http://www.cherrypy.org/wiki/ProfilingOnDebian for details.
  warnings.warn(msg)
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:239: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:263: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:281: Warning: 'as' will become a reserved keyword in Python 2.6
Selected and implied templates:
  Pylons#pylons  Pylons application template

Variables:
  egg:      helloworld
  package:  helloworld
  project:  helloworld
Enter template_engine (mako/genshi/jinja/etc: Template language) ['mako']:
Enter sqlalchemy (True/False: Include SQLAlchemy 0.4 configuration) [False]:
Enter google_app_engine (True/False: Setup default appropriate for Google App Engine) [False]:
Creating template pylons
Creating directory ./helloworld
  Recursing into +package+
    Creating ./helloworld/helloworld/
    Copying templates/default_project/+package+/__init__.py_tmpl to ./helloworld/helloworld/__init__.py
    Recursing into config
      Creating ./helloworld/helloworld/config/
      Copying templates/default_project/+package+/config/__init__.py_tmpl to ./helloworld/helloworld/config/__init__.py
      Copying templates/default_project/+package+/config/deployment.ini_tmpl_tmpl to ./helloworld/helloworld/config/deployment.ini_tmpl
      Copying templates/default_project/+package+/config/environment.py_tmpl to ./helloworld/helloworld/config/environment.py
      Copying templates/default_project/+package+/config/middleware.py_tmpl to ./helloworld/helloworld/config/middleware.py
      Copying templates/default_project/+package+/config/routing.py_tmpl to ./helloworld/helloworld/config/routing.py
    Recursing into controllers
      Creating ./helloworld/helloworld/controllers/
      Copying templates/default_project/+package+/controllers/__init__.py_tmpl to ./helloworld/helloworld/controllers/__init__.py
      Copying templates/default_project/+package+/controllers/error.py_tmpl to ./helloworld/helloworld/controllers/error.py
    Recursing into lib
      Creating ./helloworld/helloworld/lib/
      Copying templates/default_project/+package+/lib/__init__.py_tmpl to ./helloworld/helloworld/lib/__init__.py
      Copying templates/default_project/+package+/lib/app_globals.py_tmpl to ./helloworld/helloworld/lib/app_globals.py
      Copying templates/default_project/+package+/lib/base.py_tmpl to ./helloworld/helloworld/lib/base.py
      Copying templates/default_project/+package+/lib/helpers.py_tmpl to ./helloworld/helloworld/lib/helpers.py
    Recursing into model
      Creating ./helloworld/helloworld/model/
      Copying templates/default_project/+package+/model/__init__.py_tmpl to ./helloworld/helloworld/model/__init__.py
    Recursing into public
      Creating ./helloworld/helloworld/public/
      Copying templates/default_project/+package+/public/bg.png to ./helloworld/helloworld/public/bg.png
      Copying templates/default_project/+package+/public/index.html_tmpl to ./helloworld/helloworld/public/index.html
      Copying templates/default_project/+package+/public/pylons-logo.gif to ./helloworld/helloworld/public/pylons-logo.gif
    Recursing into templates
      Creating ./helloworld/helloworld/templates/
    Recursing into tests
      Creating ./helloworld/helloworld/tests/
      Copying templates/default_project/+package+/tests/__init__.py_tmpl to ./helloworld/helloworld/tests/__init__.py
      Recursing into functional
        Creating ./helloworld/helloworld/tests/functional/
        Copying templates/default_project/+package+/tests/functional/__init__.py_tmpl to ./helloworld/helloworld/tests/functional/__init__.py
      Copying templates/default_project/+package+/tests/test_models.py_tmpl to ./helloworld/helloworld/tests/test_models.py
    Copying templates/default_project/+package+/websetup.py_tmpl to ./helloworld/helloworld/websetup.py
  Copying templates/default_project/MANIFEST.in_tmpl to ./helloworld/MANIFEST.in
  Copying templates/default_project/README.txt_tmpl to ./helloworld/README.txt
  Copying templates/default_project/development.ini_tmpl to ./helloworld/development.ini
  Recursing into docs
    Creating ./helloworld/docs/
    Copying templates/default_project/docs/index.txt_tmpl to ./helloworld/docs/index.txt
  Copying templates/default_project/ez_setup.py to ./helloworld/ez_setup.py
  Copying templates/default_project/setup.cfg_tmpl to ./helloworld/setup.cfg
  Copying templates/default_project/setup.py_tmpl to ./helloworld/setup.py
  Copying templates/default_project/test.ini_tmpl to ./helloworld/test.ini
Running /usr/bin/python setup.py egg_info 

سيطلب منك 3 اجابات
1- ال template engine والإفتراضى هو mako
2- دعم sqlalchemy فى التطبيق والإفتراضى لا
3- تجهيز خيارات ل Google App Engine

الهيكلية
Code: [Select]
 |-- MANIFEST.in 
|-- README.txt
|-- development.ini
|-- docs
|   `-- index.txt
|-- ez_setup.py
|-- helloworld
|   |-- __init__.py
|   |-- config
|   |   |-- __init__.py
|   |   |-- deployment.ini_tmpl
|   |   |-- environment.py
|   |   |-- middleware.py
|   |   `-- routing.py
|   |-- controllers
|   |   |-- __init__.py
|   |   `-- error.py
|   |-- lib
|   |   |-- __init__.py
|   |   |-- app_globals.py
|   |   |-- base.py
|   |   `-- helpers.py
|   |-- model
|   |   `-- __init__.py
|   |-- public
|   |   |-- bg.png
|   |   |-- index.html
|   |   `-- pylons-logo.gif
|   |-- templates
|   |-- tests
|   |   |-- __init__.py
|   |   |-- functional
|   |   |   `-- __init__.py
|   |   `-- test_models.py
|   `-- websetup.py
|-- helloworld.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   |-- paster_plugins.txt
|   |-- requires.txt
|   `-- top_level.txt
|-- setup.cfg
|-- setup.py
`-- test.ini

ننشئ controller (وهو مايحوى ال actions مثل ال views اللتى فى grok او webpy)
Code: [Select]
 striky@striky-desktop:~/workspace/pytut/src/nettut/helloworld$ paster controller hello 
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/__init__.py:98: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/CherryPy-2.3.0-py2.5.egg/cherrypy/lib/profiler.py:54: UserWarning: Your installation of Python doesn't have a profile module. If you're on Debian, you can apt-get python2.4-profiler from non-free in a separate step. See http://www.cherrypy.org/wiki/ProfilingOnDebian for details.
  warnings.warn(msg)
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:239: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:263: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:281: Warning: 'as' will become a reserved keyword in Python 2.6
Creating /home/striky/workspace/pytut/src/nettut/helloworld/helloworld/controllers/hello.py
Creating /home/striky/workspace/pytut/src/nettut/helloworld/helloworld/tests/functional/test_hello.py
striky@striky-desktop:~/workspace/pytut/src/nettut/helloworld$


تمام افتح الملف فى المسار helloworld/controllers/hello ستجده مشابه للتالى
Code: [Select]
import logging 

from pylons import request, response, session, tmpl_context as c
from pylons.controllers.util import abort, redirect_to

from helloworld.lib.base import BaseController, render
#from helloworld import model

log = logging.getLogger(__name__)

class HelloController(BaseController):

    def index(self):
        # Return a rendered template
        #   return render('/template.mako')
        # or, Return a response
        return 'Hello World'
 

يتم التعامل مع العناوين كالتالى
Code: [Select]
 mysite.com/controller/view

مثلا عن ارسال
Code: [Select]
mysite.com/hello/index 

فيتم استدعاء الكنترولر (المقسم) hello ومنه يتم اختيار ال action المناسبة
قم بتشغيل السرفر
Code: [Select]
striky@striky-desktop:~/workspace/pytut/src/nettut/helloworld$ paster serve --reload development.ini  

ملف ال development.ini يحوى معلومات عن البيئة كالهوست والبورت  ومتغيرات التطبيق الخ الخ


الآن اكتب hello/index فى العنوان




Turbogears
[/b]
تربوجيرز هى اطار عمل رائع يقوم على ربط التقنيات الحالية فى عالم بايثون للخروج بأفضل نتيجة فللتعامل مع قواعد البيانات يتم استخدام SQLAlchemy او SQLObject وللتعامل مع الtemplates يتم استخدام kid وهكذا

لتستيب تربوجيرز قم اولا بتحميل الحزمة من الموقع http://turbogears.org/
راجع صفحة التستيب http://docs.turbogears.org/1.0/Install

قم بتحميل سكربت tgsetup.py وتشغيله
http://www.turbogears.org/download/tgsetup.py

نفذ سكربت التستيب
Code: [Select]
 striky@striky-desktop:~/Desktop$ sudo python tgsetup.py
 
[sudo] password for striky:
Sorry, try again.
[sudo] password for striky:
TurboGears Installer
Beginning setuptools/EasyInstall installation and TurboGears download

Searching for TurboGears==1.0.8
Reading http://www.turbogears.org/download/
Reading http://pypi.python.org/simple/TurboGears/
Reading http://www.turbogears.org
Reading http://www.turbogears.org/
Reading http://www.turbogears.org/download/filelist.html
Best match: TurboGears 1.0.8
Downloading http://files.turbogears.org/eggs/TurboGears-1.0.8-py2.5.egg
Processing TurboGears-1.0.8-py2.5.egg
removing '/usr/lib/python2.5/site-packages/TurboGears-1.0.8-py2.5.egg' (and everything under it)
creating /usr/lib/python2.5/site-packages/TurboGears-1.0.8-py2.5.egg
Extracting TurboGears-1.0.8-py2.5.egg to /usr/lib/python2.5/site-packages
Removing TurboGears 1.0.7 from easy-install.pth file
Adding TurboGears 1.0.8 to easy-install.pth file
Installing tg-admin script to /usr/bin

Installed /usr/lib/python2.5/site-packages/TurboGears-1.0.8-py2.5.egg
Reading http://files.turbogears.org/eggs/
Processing dependencies for TurboGears==1.0.8
Searching for Extremes>=1.1
Reading http://pypi.python.org/simple/Extremes/
Best match: Extremes 1.1
Downloading http://pypi.python.org/packages/2.5/E/Extremes/Extremes-1.1-py2.5.egg#md5=4015e2546295858558cca16faca5f34f
Processing Extremes-1.1-py2.5.egg
Moving Extremes-1.1-py2.5.egg to /usr/lib/python2.5/site-packages
Adding Extremes 1.1 to easy-install.pth file

Installed /usr/lib/python2.5/site-packages/Extremes-1.1-py2.5.egg
Searching for PyProtocols>=1.0a0dev-r2302
Reading http://pypi.python.org/simple/PyProtocols/
Reading http://peak.telecommunity.com/PyProtocols.html
Reading http://peak.telecommunity.com/dist/
Best match: PyProtocols 1.0a0dev-r2302
Downloading http://files.turbogears.org/eggs/PyProtocols-1.0a0dev_r2302-py2.5-linux-i686.egg
Processing PyProtocols-1.0a0dev_r2302-py2.5-linux-i686.egg
Moving PyProtocols-1.0a0dev_r2302-py2.5-linux-i686.egg to /usr/lib/python2.5/site-packages
Adding PyProtocols 1.0a0dev-r2302 to easy-install.pth file

Installed /usr/lib/python2.5/site-packages/PyProtocols-1.0a0dev_r2302-py2.5-linux-i686.egg
Finished processing dependencies for TurboGears==1.0.8


Hello World: TG
لإنشاء تطبيق سريع كل ماعليك هو تنفيذ tg-admin quickstart
Code: [Select]
 striky@striky-desktop:~/workspace/pytut/src/nettut$ tg-admin  quickstart 
/usr/lib/python2.5/site-packages/CherryPy-2.3.0-py2.5.egg/cherrypy/lib/profiler.py:54: UserWarning: Your installation of Python doesn't have a profile module. If you're on Debian, you can apt-get python2.4-profiler from non-free in a separate step. See http://www.cherrypy.org/wiki/ProfilingOnDebian for details.
  warnings.warn(msg)
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/__init__.py:98: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:239: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:263: Warning: 'as' will become a reserved keyword in Python 2.6
/usr/lib/python2.5/site-packages/RuleDispatch-0.5a1.dev_r2506-py2.5-linux-i686.egg/dispatch/predicates.py:281: Warning: 'as' will become a reserved keyword in Python 2.6
Enter project name: hello
Enter package name [hello]: hello
Do you need Identity (usernames/passwords) in this project? [no]
Selected and implied templates:
  TurboGears#tgbase      tg base template
  TurboGears#turbogears  web framework

Variables:
  egg:               hello
  elixir:            False
  identity:          none
  package:           hello
  project:           hello
  sqlalchemy:        False
  sqlobject:         True
  sqlobjectversion:  SQLObject>=0.10.1
Creating template tgbase
Creating directory ./hello
  Recursing into +einame+.egg-info
    Creating ./hello/hello.egg-info/
    Copying PKG-INFO to ./hello/hello.egg-info/PKG-INFO
    Copying paster_plugins.txt to ./hello/hello.egg-info/paster_plugins.txt
    Copying sqlobject.txt_tmpl to ./hello/hello.egg-info/sqlobject.txt
  Recursing into +package+
    Creating ./hello/hello/
    Copying __init__.py to ./hello/hello/__init__.py
    Copying release.py_tmpl to ./hello/hello/release.py
    Recursing into static
      Creating ./hello/hello/static/
      Recursing into css
        Creating ./hello/hello/static/css/
Skipping file /usr/lib/python2.5/site-packages/TurboGears-1.0.8-py2.5.egg/turbogears/qstemplates/qsbase/+package+/static/css/empty_tmpl
      Recursing into images
        Creating ./hello/hello/static/images/
        Copying favicon.ico to ./hello/hello/static/images/favicon.ico
        Copying tg_under_the_hood.png to ./hello/hello/static/images/tg_under_the_hood.png
        Copying under_the_hood_blue.png to ./hello/hello/static/images/under_the_hood_blue.png
      Recursing into javascript
        Creating ./hello/hello/static/javascript/
Skipping file /usr/lib/python2.5/site-packages/TurboGears-1.0.8-py2.5.egg/turbogears/qstemplates/qsbase/+package+/static/javascript/empty_tmpl
    Recursing into templates
      Creating ./hello/hello/templates/
      Copying __init__.py to ./hello/hello/templates/__init__.py
Creating template turbogears
  Recursing into +package+
    Copying commands.py_tmpl to ./hello/hello/commands.py
    Recursing into config
      Creating ./hello/hello/config/
      Copying __init__.py to ./hello/hello/config/__init__.py
      Copying app.cfg_tmpl to ./hello/hello/config/app.cfg
      Copying log.cfg_tmpl to ./hello/hello/config/log.cfg
    Copying controllers.py_tmpl to ./hello/hello/controllers.py
    Copying json.py_tmpl to ./hello/hello/json.py
    Copying model.py_tmpl to ./hello/hello/model.py
    Recursing into static
      Recursing into css
        Copying style.css to ./hello/hello/static/css/style.css
      Recursing into images
        Copying header_inner.png to ./hello/hello/static/images/header_inner.png
        Copying info.png to ./hello/hello/static/images/info.png
        Copying ok.png to ./hello/hello/static/images/ok.png
    Recursing into templates
      Copying login.kid to ./hello/hello/templates/login.kid
      Copying master.kid to ./hello/hello/templates/master.kid
      Copying welcome.kid to ./hello/hello/templates/welcome.kid
    Recursing into tests
      Creating ./hello/hello/tests/
      Copying __init__.py to ./hello/hello/tests/__init__.py
      Copying test_controllers.py_tmpl to ./hello/hello/tests/test_controllers.py
      Copying test_model.py_tmpl to ./hello/hello/tests/test_model.py
  Copying README.txt_tmpl to ./hello/README.txt
  Copying dev.cfg_tmpl to ./hello/dev.cfg
  Copying sample-prod.cfg_tmpl to ./hello/sample-prod.cfg
  Copying setup.py_tmpl to ./hello/setup.py
  Copying start-+package+.py_tmpl to ./hello/start-hello.py
  Copying test.cfg_tmpl to ./hello/test.cfg
Running /usr/bin/python setup.py egg_info
Manually creating paster_plugins.txt (deprecated! pass a paster_plugins keyword to setup() instead)
Adding TurboGears to paster_plugins.txt
running egg_info
paster_plugins not set in setup(), but hello.egg-info/paster_plugins.txt exists
writing requirements to hello.egg-info/requires.txt
writing hello.egg-info/PKG-INFO
writing top-level names to hello.egg-info/top_level.txt
writing dependency_links to hello.egg-info/dependency_links.txt
writing entry points to hello.egg-info/entry_points.txt
reading manifest file 'hello.egg-info/SOURCES.txt'
writing manifest file 'hello.egg-info/SOURCES.txt'
striky@striky-desktop:~/workspace/pytut/src/nettut$

لإختيار البورت اللذى تريد الإنصات عليه قم بتحرير ملف dev.cfg حيث يشمل اعدادات التطبيق
Code: [Select]
 server.socket_port=40003

مسار قاعدة بيانات sqlite
Code: [Select]
 sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"

اذا قمت بعمل اى جداول .. الخ
قم بتشغيل التطبيق بإستخدام ال start script وهنا ستجد اسمه start-hello.py
افتح متصفحك وحدد العنوان localhost:40003 او غيره اذا قمت بإعداد البورت  ستشاهد صفحة مثل هذه


بنفس فلسفة pylons ستجد المتحكمات (controllers) فى ملف controllers.py
Code: [Select]
 #controllers.py
import turbogears as tg
from turbogears import controllers, expose, flash
# from hello import model
# import logging
# log = logging.getLogger("hello.controllers")

class Root(controllers.RootController):
    @expose(template="hello.templates.welcome")
    def index(self):
        import time
        # log.debug("Happy TurboGears Controller Responding For Duty")
        flash("Your application is now running")
        return dict(now=time.ctime())

وهذا هو الcontroller الرئيسى وتم كشفه لل template فى المسار hello/templates/welcome.kid
ملحوظة لكشف اى action لtemplate ما استخدم @expose وضيف ليها معامل template وقيمته = مسار الtemplate المطلوب

ملف welcome.kid
Code: [Select]
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
    py:extends="'master.kid'">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
<title>Welcome to TurboGears</title>
</head>
<body>

  <div id="sidebar">
    <h2>Learn more</h2>
    Learn more about TurboGears and take part in its
    development
    <ul class="links">
      <li><a href="http://www.turbogears.org">Official website</a></li>
      <li><a href="http://docs.turbogears.org">Documentation</a></li>
      <li><a href="http://trac.turbogears.org/turbogears/">Trac
        (bugs/suggestions)</a></li>
      <li><a href="http://groups.google.com/group/turbogears"> Mailing list</a> </li>
    </ul>
    <span py:replace="now">now</span>
  </div>
  <div id="getting_started">
    <ol id="getting_started_steps">
      <li class="getting_started">
        <h3>Model</h3>
        <p> <a href="http://docs.turbogears.org/1.0/GettingStarted/DefineDatabase">Design models</a> in the <span class="code">model.py</span>.<br/>
          Edit <span class="code">dev.cfg</span> to <a href="http://docs.turbogears.org/1.0/GettingStarted/UseDatabase">use a different backend</a>, or start with a pre-configured SQLite database. <br/>
          Use script <span class="code">tg-admin sql create</span> to create the database tables.</p>
      </li>
      <li class="getting_started">
        <h3>View</h3>
        <p> Edit <a href="http://docs.turbogears.org/1.0/GettingStarted/Kid">html-like templates</a> in the <span class="code">/templates</span> folder;<br/>
        Put all <a href="http://docs.turbogears.org/1.0/StaticFiles">static contents</a> in the <span class="code">/static</span> folder. </p>
      </li>
      <li class="getting_started">
        <h3>Controller</h3>
        <p> Edit <span class="code"> controllers.py</span> and <a href="http://docs.turbogears.org/1.0/GettingStarted/CherryPy">build your
          website structure</a> with the simplicity of Python objects. <br/>
          TurboGears will automatically reload itself when you modify your project. </p>
      </li>
    </ol>
    <div class="notice"> If you create something cool, please <a href="http://groups.google.com/group/turbogears">let people know</a>, and consider contributing something back to the <a href="http://groups.google.com/group/turbogears">community</a>.</div>
  </div>
  <!-- End of getting_started -->
</body>
</html>

تعالى نجرب اضافة action جديد وليكن greet
بكل بساطة ضيفه فى ال controllers.py كطريقة لل RootController
Code: [Select]
        
    @expose(template='hello.templates.greet')
    def greet(self, who='World'):
    return dict(g='Hello, '+who)
   

ماهذا ؟ ايه معنى who ؟
بكل بساطة هى معامل يتم استدعائه بعد اسم ال action فى العنوان مثلا
localhost:40003/hello/Ahmed
فتصبح قيمة who هى Ahmed وفى حال عدم تحديدها تكون قيمتها World
نعيد dict من تلك ال action يشمل المتغيرات اللتى ستصبح مكشوفة فى ال template ليتم استخدامها فيه


عند الإستدعاء بدون معاملات



بإستخدام معاملات



يوجد اطارات عمل اكثر من رائعة مثل Django التى لم نتعرض لها فى الكتاب وايضا Web2Py  وغيرها
تجد قائمة بأهم اطر العمل هنا
http://wiki.python.org/moin/WebFrameworks


« Last Edit: January 11, 2009, 04:17:58 PM by Ahmed Youssef »
Logged

Life is just a chance to grow a soul. - A. Powell
Weblog: http://ahmedyoussef.wordpress.com/