در اين بخش و بخش های بعدی به معرفی TurboGears، فريم ورکی برای توليد برنامه های تحت وب خواهم پرداخت. هدف من از اين سری مطالب آموزش TurboGears نيست، بلکه می خواهم شما حسی نسبت به چگونگی توليد برنامه های کاربردی تحت وب با استفاده از TurboGears و امکاناتی که در اختيار شما قرار می دهد پيدا کنيد، و بتوانيد تصميم بگيريد که آيا TurboGears برای نيازهای شما مناسب است يا نه.
TurboGears يک زبان جديد نيست، بلکه يک سری ابزار و کتابخانه ی برنامه نويسی است که با استفاده از آن می توانيد برنامه های تحت وب ايجاد کنيد. زبان برنامه نويسی که TurboGears از آن استفاده می کند Python است.
TurboGears مبتنی بر معماری Model-View-Controller می باشد و برنامه نويس را هدايت به جدا کردن اين سه لايه از يکديگر می کند.
ديگر در TurboGears نيازی به نوشتن دستورات پيچيده ی SQL نيست. مثلا اگر بخواهيم يک جدول به نام User داشته باشيم که دارای فيلدهای name و email باشد، کافی است کلاسی به اسم User که از کلاس SQLObject مشتق می شود ايجاد کنيم:
class User(SQLObject): name = StringCol() email = StringCol()
class User(SQLObject): name = StringCol() email = StringCol() friends = MultipleJoin('User')
class User(SQLObject): … def FriendCount(): return friends.count()
hadi = User(name = "Hadi", email = "hadi@pykello.net")
hadi.email = "irancoldfusion@yahoo.com"
hadi.destroySelf()
result = User.selectBy(name = "Hadi")
sqlobject.dburi = "sqlite:///home/brian/tutorial/tutorial.sqlite"
خيلی خوبه، مگه نه؟
در قسمت های بعدی بيشتر به بحث امکاناتی که TurboGears در رابطه با مدل داده ای در اختيار ما می گذارد خواهم پرداخت.
رفتار برنامه ی شما در فايل controllers.py توصيف می شود.
توجه: در ادامه فرض می کنم که URL برنامه ی ما /http://localhost است.
مثلا اگر می خواهيد صفحه ی /http://localhost (و همچنين http://localhost/index) عبارت !Hello World را نمايش دهد:
class Root(controllers.RootController): @expose() def index(self): return "Hello World!"
در واقع کلاس Root متناظر با مسير اصلی (يعنی http://localhost/ ) متناظر است، و توابع کلاس Root متناظر با صفحات شما. حال اگر بخواهيم پارامترهايي را به يک صفحه پاس کنيم:
class Root(controllers.RootController): … @expose() def showmessage(self, name = "Hadi"): return "Hello " + name
حال اگر با استفاده از مرورگر وب مسير http://localhost/showmessage را مشاهده کنيد، عبارت Hello Hadi را مشاهده می کنيد، و مسير http://localhost/showmessage?name=pykello عبارت Hello pykello را نمايش می دهد.
اکنون اگر بخواهيم آدرس ايميل کاربری را از پايگاه داده استخراج کنيم و نمايش دهيم:
class Root(controllers.RootController): … @expose() def showemail(self, name="hadi"): result = User.selectBy(name = name) if result.count() == 0: return "No such user!" else: return "The email address is " + result[0].email
در صورتی که هيچ تابعی برای مديريت صفحه ی مورد نظر موجود نباشد، تابع default فراخوانی می شود:
class Root(controllers.RootController): … @expose() def default(self, methodname): return methodname + " not found"
اگر بخواهيم آدرس هايي با فرمت http://localhost/~username آدرس ايميل متناظر با username را نشان دهد:
class Root(controllers.RootController): … @expose() def default(self, methodname): ifre.match("^~[\w\d]+$", methodname): # a regular expression matching return showemail(methodname[1:])# i.e. suffix starting from second character else: return "Page not found!"
مثال هايي که در بخش قبلی نشان داديم، تنها متن ساده به عنوان خروجی ايجاد می کردند. اگر بخواهيم صفحات خوشگل ايجاد کنيم، روش بخش قبل کثيف و پردردسر است.
TurboGears اين امکان را در اختيار ما می گذارد که لايه ی نمايش را با استفاده از template ها توصيف کنيم.مثلا، اگر مسيری که پروژه ی ما در آن ذخيره شده باشد c:\tutorial باشد، برای اينکه يک تابع در لايه ی کنترلر از template موجود در c:\tutorial\tutorial\templates\user.kid استفاده کند:
class Root(controllers.RootController): … @expose(template="tutorial.templates.user") def showemail(self, name = "hadi"): result = User.selectBy(name = name) return dict(name = name, email = result[0].email)
و فايل user.kid:
<html> <head><title>Welcome to TurboGears!</title></head> <body>The email address for user $name is $email .</body> </html>
در قسمت های بعدی بيشتر به ايجاد template ها و امکانات خواهم پرداخت.
در قسمت قبل چندين مثال ساده در رابطه با مدل داده ای مطرح کرديم. در اين قسمت مثال های بيشتری مطرح می کنم.
همان طور که قبلا گفتم، برای مشخص کردن نوع و مشخصات پايگاه داده ی مورد استفاده در برنامه ی تحت وبمان، بايد فايل dev.cfg را تغيير دهيم و سطری مشابه سطر زير در آن ايجاد کنيم:
sqlobject.dburi = "sqlite:///home/brian/tutorial/tutorial.sqlite"
در مثال بالا، نوع پايگاه داده ی مورد استفاده (sqlite) و مسيری که فايل پايگاه داده در آن ذخيره می شود ذکر شده است. در زير چند مثال ديگر مشاهده می کنيد که پايگاه داده هايي از نوع MySQLو PostgreSQL را مشخص می کنند:
mysql://user:password@host/database mysql://host/database?debug=1 postgres://user@host/database?debug=&cache= postgres:///full/path/to/socket/database postgres://host:5432/database
برای ايجاد کردن ارتباط يک به چند:
class Address(SQLObject): Country = StringCol() City = StringCol() StreetAddress = StringCol() Owner = ForeignKey("Person") class Person(SQLObject): name = StringCol() addresses = MultipleJoin('Address')
در مثال بالا، هر آدرس متعلق به تنها يک شخص است، ولی يک شخص می تواند دارای چندين آدرس باشد.
مثال ديگر در ارتباط با تعريف جداول همراه با توضيحات:
class Person(SQLObject): email = StringCol(alternateID = True)# email is an index column for the table name = StringCol(unique = True)# no duplicate values for name birthdate = DateCol(notNone = True)# birthdate cannot be without value # maritalStatus can be either 'Single' or 'Married', and its default value is 'Single' maritalStatus = EnumCol(enumValues=['Single', 'Married'], default='Single')
لازم به ذکر است که هر کدام از جداول به طور پيش فرض دارای فيلدی به نام id هستند که به عنوان Primary Key به کار می رود.برای انتخاب رکوردها با استفاده از مقادير فيلد ها:
result = Person.selectBy(name = "Hadi", maritalStatus = 'Single')
برای انتخاب رکوردها با استفاده از فيلدهای ايندکس:
result = Person.byEmail('hadi@pykello.net')
برای مشخص کردن Query با استفاده از زبان SQL:
result = Person._connection.queryAll('Select * from Person')
برای بدست آوردن تعداد رکوردها موجود در نتيجه:
count = result.count()
برای بدست آوردن رکورد اول موجود در نتيجه و تغيير يکی از فيلدهای آن:
firstPerson = result[0] firstPerson.name = "Hadi Moshayedi"
TurboGears برای ارتباط با پايگاه داده از SQLObject استفاده می کند. برای آشنايي بيشتر با امکانات SQLObject به مستندات SQLObject مراجعه کنيد.