Python Web çerçeveleri, Bölüm 2: TurboGears ve Python ile Web geliştirmesi

0
butch
IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.
developerWorks  >  Linux | Açık kaynak | Web mimarisi  >

Python Web çerçeveleri, Bölüm 2: TurboGears ve Python ile Web geliştirmesi

Çevrimiçi bir alışveriş uygulaması temel özellikleri gösterir

Düzey: Orta

Ian Maurer (ian@itmaurer.com), Üst Düzey Danışman, Brulant, Inc.

11 Temmuz 2006

İki bölümlük dizinin bu ikinci makalesinde, Python'a dayalı olan açık kaynak MVC biçimindeki bir Web uygulaması çerçevesi olan TurboGears'i tanıtacağız. İlk makale Django çerçevesine giriş olarak yazılmıştır; bu makalede ise Web tabanlı bir alışveriş uygulaması yaratmak için TurboGears'ı nasıl kullanacağınız anlatılır ve sonunda Turbogears ile Django birbiriyle karşılaştırılır.

TurboGears geliştiricileri bu projeyi bir "mega çerçeve" olarak adlandırır, çünkü bu daha önce var olan çeşitli alt projelerden oluşur. TurboGears birkaç ana bileşenin biraraya getirilmesine yardımcı olur:

  • MochiKit: JavaScript kitaplığı
  • Kid: Şablon oluşturma dili
  • CherryPy: Temel Web çerçevesi
  • SQLObject: Nesne ile ilişkisel eşleyici (ORM)

TurboGears'ın Kurulması

TurboGears ile çalışmanın ilk adımı, Python'un mutlaka kurulu olduğundan emin olmaktır. TurboGears'ın en son sürümü için Python 2.4 gereklidir. Python ana sayfası bağlantısı için, Kaynaklar bölümüne bakın.

Python topluluğunun sunduğu yeni bir proje olan Setuptools (kuruluş araçları), Python yazılımının kurulmasını ve güncellenmesini oldukça kolaylaştırır. Yazılım, Egg olarak adlandırılan ve bir Java™ JAR dosyasına ya da bir Ruby GEM dosyasına benzeyen bir arşiv dosyasında bulunur, easy_install adı verilen bir araç tarafından yüklenir ve kurulur.

TurboGears, dağıtım ve kuruluş için Setuptools'u kullanan ilk büyük Python projelerinden biridir. Setuptools sayfasına ve Turbogears yükleme sayfasına bağlantı için Kaynaklar bölümüne bakın.

Bu makalede, makalenin yazıldığı sırada en son geliştirme sürümü (0.9a5) kullanılmıştır ve bu sürüm önizleme yükleme sayfasından alınabilir:

easy_install -f http://www.turbogears.org/preview/download/index.html TurboGears

TurboGears'ın en son sabit sürümünü (0.8.9 geçerli) almak için tek yapmanız gereken, -f seçeneğini ve önizleme sitesi URL'sini kaldırmaktır:

easy_install TurboGears

TurboGears admin (yönetim) aracının denetlenmesi

TurboGears'ı kurduktan sonra, yolunuz üzerinde tg-admin adlı admin (yönetim) aracınızın bulunması gerekir. Komut satırında tg-admin yazarak bunu denetleyin:


Liste 1. TurboGears yönetim aracının kullanılması
~/dev$ tg-admin

TurboGears 0.9a5 command line interface

Usage: /usr/bin/tg-admin [command] [options]

Available commands:
      i18n  Manage i18n data
      info  Show version info
quickstart  Create a new TurboGears project
     shell  Start a Python prompt with your database available
       sql  Run the SQLObject manager
   toolbox  Launch the TurboGears Toolbox
    update  Update an existing turbogears project



Quick start (Hızlı başlangıç)

Bir TurboGears projesine başlamak için, tg-admin quickstart işlevini kullanın. Başlarken sizden hem bir proje adı, hem de bir dizin adı sağlamanız istenir. Bu makale için, paket adı tgcommerce olan TG Commerce adlı basit bir alışveriş sepeti örneği yarattım:


Liste 2. Bir TurboGears projesine başlama
~/dev$ tg-admin quickstart
Enter project name: TG Commerce
Enter package name [tgcommerce]:
Selected and implied templates:
  turbogears#turbogears  web framework

Variables:
  package:  tgcommerce
  project:  TG-Commerce
Creating template turbogears
  Creating ./TG-Commerce/

    ... (output snipped) ...

TurboGears, altında tgcommerce paketi olan bir TG-Commerce proje dizini yaratır. Artık projenizle birlikte gelen test sunucunuzu çalıştırabilirsiniz:


Liste 3. Test sunucusunun başlatılması
~/dev/TG-Commerce$ python start-tgcommerce.py

... (output snipped) ...

05/Mar/2006:11:31:54 HTTP INFO Serving HTTP on http://localhost:8080/

Sağlanan URL'deki test sayfasını gözden geçirin, daha sonra Ctrl-C tuşlarını kullanarak sunucuyu sonlandırın.



Bir model yaratılması

SQLObject, veritabanı bazında tutarlı Python nesneleri geliştirmenizi sağlayan bir nesne ile ilişkisel eşleyici (ORM) kitaplığıdır. Burada bir Python sınıfı tanımlarsınız, istenen öznitelikleri (alanları) eklersiniz; sonra tablo yaratmak, yeni kayıt eklemek, var olan kayıtları bulmak, güncellemek ya da silmek için gereken SQL oluşturma işlemini SQLObject yönetir.

SQLObject, MySQL, PostgreSQL, Firebird ve diğerlerini de içeren çeşitli veritabanlarını destekler. Kaynaklar bölümündeki bağlantıyı tıklatarak SQLObject'e ilişkin daha fazla bilgi edinebilirsiniz.

Bu örnekte, veritabanı arka ucu olarak SQLite kullanılmıştır. SQLite, hiçbir yapılandırma gerektirmeyen ve diskte basit bir dosya olarak yer alan basit bir veritabanıdır. SQLite'ı kullanmak için, setuptools yoluyla pysqlite kitaplığını kurun:

easy_install pysqlite

TurboGears veritabanını yapılandırmak için, dev.cfg dosyasında sqlobject.dburi komutunu yazın. SQLite için, veritabanı dosyasının yer almasını istediğiniz yolu belirtin:


Liste 4. Geliştirme yapılandırma dosyası (dev.cfg)
sqlobject.dburi="notrans_sqlite:///path/to/devdir/TG-Commerce/tgcommerce.database"
server.environment="development"
autoreload.package="tgcommerce"

TurboGears quickstart, model.py dosyasını yaratır ve önceden içine bir ortak kod yerleştirir. Burası, SQLObject sınıflarının yerleştirilmesi gereken yerdir. Üstte, veritabanı bağlantısı göbeğini (hub) oluşturan bölüm vardır:


Liste 5. Model ortak kodu (model.py)
from sqlobject import *
from turbogears.database import PackageHub

hub = PackageHub("tgcommerce")
__connection__ = hub

Daha sonra sıra, model sınıflarına gelir. Her biri, veritabanında, veritabanı sütunlarıyla eşleşen sınıf düzeyi öznitelikleriyle tanımlanan bir tabloyu temsil eder. Bu öznitelikler, StringCol ve CurrencyCol gibi temel veri tipleriyle, ForeignKey ve MultipleJoin gibi ilişki tiplerini içeren SQLObject sütun tiplerinin eşgörünümleridir.

Bu alışveriş sepeti, hiyerarşik bir Category (Kategori) ve basit bir Product (Ürün) sınıfı içermektedir. Kategori hiyerarşisi, ana ForeignKey öğesi ve alt kategoriler MultipleJoin tarafından tanımlanır.


Liste 6. Kategori ve Ürün sınıfları (model.py, devam)
class Category(SQLObject):
    name = StringCol(length=64)
    parent = ForeignKey('Category', default=None)
    subcategories = MultipleJoin('Category', joinColumn='parent_id')
    products = MultipleJoin('Product')

class Product(SQLObject):
    name = StringCol(length=64)
    sku = StringCol(length=64)
    price = CurrencyCol(notNone=True, default=0.0)
    category = ForeignKey('Category')

Modeli doğrulamak için, gereksinim duyulan tabloları yaratacak olan SQL kodunu görüntülemek üzere tg-admin sql sql komutunu kullanın. SQLObject'in her bir tablo için bir id (tanıtıcı) sütunu yarattığına dikkat edin. Bu durum, hiçbir birincil anahtar tanımlanmadığında oluşur. SQLObject hakkındaki belgelere ve bağlantılara ulaşmak için, Kaynaklar başlıklı bölüme bakın.


Liste 7. 'tg-admin sql sql' komutunu kullanarak veritabanı şemasının görüntülenmesi
~/dev/TG-Commerce$ tg-admin sql sql
Using database URI sqlite:///home/ubuntu/dev/TG-Commerce/tgcommerce.db
CREATE TABLE category (
    id INTEGER PRIMARY KEY,
    name VARCHAR(64),
    parent_id INT
);

CREATE TABLE product (
    id INTEGER PRIMARY KEY,
    name VARCHAR(64),
    sku VARCHAR(64),
    price DECIMAL(10, 2) NOT NULL,
    category_id INT
);

Aşağıda, alışveriş sepetini ve bunun içindeki kalemleri saklamak için kullanılan Order (Sipariş) ve OrderItem (Sipariş Kalemi) sınıfları görülmektedir. order bir SQL anahtar sözcüğü olduğu için, Order sınıfına ilişkin tablo adı, sqlmeta altsınıfının tablo öznitelikleri kullanılarak orders'ta yeniden tanımlanır:


Liste 8. Order (Sipariş) ve OrderItem (Sipariş Kalemi) sınıfları (model.py, devam)
class Order(SQLObject):
    items = MultipleJoin('OrderItem', joinColumn='order_id')

    class sqlmeta:
        table = 'orders'

class OrderItem(SQLObject):
    quantity = IntCol(notNone=True)
    price = CurrencyCol(notNone=True)
    total = CurrencyCol(notNone=True)
    order = ForeignKey('Order')
    product = ForeignKey('Product')

Veritabanı tablolarını yaratmak için tg-admin sql create komutunu kullanın:


Liste 9. 'tg-admin sql create' komutunu kullanarak veritabanı tablolarının yaratılması
~/dev$ tg-admin sql create
Using database URI sqlite:///home/ubuntu/dev/TG-Commerce/tgcommerce.db

tg-admin sql help komutunu kullanarak, tabloları bırakma komutu da dahil olmak üzere pek çok komut bulabilirsiniz. Bu komutu kullanırken çok dikkatli olun, çünkü bu komut, içerdikleri verilerle birlikte tüm tablolarınızı da siler. Yalnızca bu nedenle bile, tg-admin komutunun üretim ortamında kilitlenmesi gerekir.



Modelin CatWalk ile kullanılması

TurboGears, sürüm 0.9'dan başlayarak, Toolbox adı verilen ve CatWalk aldı bir model tarayıcısını içeren bir araç takımıyla birlikte sağlanır. CatWalk, bir GUI aracı kullanarak modelleri için hızlı bir biçimde veri yaratmak, güncellemek ve silmek isteyen geliştiricilere yönelik olarak tasarlanmıştır.

Toolbox (araç kutusu) ayrı bir sunucu olarak başlatılır ve tg-admin komutu kullanılarak çalıştırılır:


Liste 10. tg-admin komutunu kullanarak Toolbox sunucusunun başlatılması
~/dev/TG-Commerce$ tg-admin toolbox
... (snip) ...
05/Mar/2006:15:01:33 HTTP INFO Serving HTTP on http://localhost:7654/

Bir tarayıcı otomatik olarak açılmazsa, Toolbox sunucusu tarafından belirtilen URL adresine (http://localhost:7654/) gidin ve CatWalk aracını açmak için CatWalk bağlantısını tıklatın.


Şekil 1. CatWalk aracı
CatWalk aracı

Toolbox, son kullanıcılara değil geliştiricilere yönelik olarak geliştirilmiştir ve veri modellemesine ve uygulamalarınıza veri önyüklemesi yapılmasına yardımcı olmak amacıyla kullanılır. Toolbox sunucusunu Ctrl-C tuşlarını kullanarak kapatabilirsiniz. Bunu bu gözden geçirme çalışmasında kullanmayacaksınız.


Bir görünüm yaratılması

TurboGears'ta görünüm yaratmak için varsayılan yol, Kid adlı XML şablon oluşturma dilinin kullanılmasıdır. Kid, XML'i kullandığı için, tüm şablonların düzgün bir biçimde oluşturulması gerekir, tersi durumda, oluşturma sırasında olağandışı bir durum ortaya çıkar. Kid ayrıca, ortak kodun tek bir yerde yaratılabilmesi ve buna bakım yapılabilmesi için türetilmiş şablonların temel şablonlardan genişletilebildiği template inheritance olanağını da destekler.

TurboGears'ta, Kid dosyaları şablonlar dizininde .kid uzantısıyla yer alır. Varsayılan değer olarak, bir master.kid dosyası ve bir welcome.kid dosyası bulunur; master.kid temel şablon dosyasıdır ve welcome.kid <html> etiketindeki py:extends özniteliğini kullanarak bundan devralır.

Yeni bir şablon yaratmak için, welcome.kid dosyasını kopyalamanızı ya da yeniden adlandırmanızı ve başlangıç noktanız olarak bunu kullanmanızı öneririm. Kategori şablonu ilk başta bu örnek için yaratılmıştı; verilen bir kategoriye ilişkin aşağıdaki bilgileri gösterir:

  • Kategori adı (başlık)
  • Önceki öğelere (ancestor) olan bağlantılar ("breadcrumbs")
  • Alt kategorilere olan bağlantılar (liste)
  • Ürünlere olan bağlantılar (liste)

Liste 11. Kategori sınıfı kid şablon dosyası (category.kid)
<!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>
    <title>Category: ${category.name}</title>
</head>

<body>
	<div id="breadcrumbs">
		<ul>
			<li py:for="ancestor in list(category.ancestors)[::-1]">
				>
				<a href="/category/${ancestor.id}"
						py:content="ancestor.name"></a>
			</li>
			<li id="active">
				> <span py:replace="category.name" />
			</li>
		</ul>
	</div>

	<div id="subcategories" py:if="category.subcategories">
		<div class="header">Subcategories</div>
		<ul>
			<li py:for="subcategory in category.subcategories">
				<a href="/category/${subcategory.id}"
						py:content="subcategory.name"></a>
			</li>
		</ul>
	</div>

	<div id="subcategories" py:if="category.products">
		<div class="header">Products</div>
		<ul>
			<li py:for="product in category.products">
				<a href="/product/${product.id}"
						py:content="product.name"></a>
			</li>
		</ul>
	</div>
</body>
</html>

Liste 11'de anahtar Kid işlevlerinden bazıları gösterilmiştir:

  • py:extends kullanılarak master.kid dosyasından devralma
  • ${category.name} kullanılarak başlıktaki anlatımı değiştirme
  • py:for kullanılarak önceki öğe (ancestor), altsınıflar ve döngüler arasında döngü gerçekleştirme
  • Breadcrumbs'taki önceki öğe (ancestor) görünümünü tersine çevirmek için dilimleme mantığını kullanma
  • py:content kullanılarak bir bağlantıdaki metni doldurma
  • py:replace kullanılarak bir yayılma etiketini değiştirme

Yukarıda sözü edilen ancestors (önceki öğeler) özniteliğinin geçerli olması için, Category model sınıfının bir _get_ancestors yöntemi içerecek biçimde değiştirilmesi gerekir:


Liste 12. Category sınıfına 'ancestors' özniteliği 'get' yöntemi eklenmesi
class Category(SQLObject):
    name = StringCol(length=64)
    parent = ForeignKey('Category', default=None)
    subcategories = MultipleJoin('Category', joinColumn='parent_id')
    products = MultipleJoin('Product')

    def _get_ancestors(self):
	ancestor = self.parent
	while ancestor:
	    yield ancestor
	    ancestor = ancestor.parent



Bir denetleyici yaratılması

TurboGears quickstart, Root (Kök) denetleyici sınıfının yeri olan controllers.py modülüne sahip bir proje sağlar. Bu, uygulamanız için ana giriş noktasıdır ve yeni denetleyici yöntemlerinin ekleneceği yerdir.

TurboGears expose dekoratörü sayesinde kategori HTML şablonlarıyla ilişkili olan iki örnek denetleyici yöntemi aşağıda gösterilmiştir. Denetleyici yöntemleri, belirtilen Kid şablonunun oluşturulması sırasında ad boşluğu ya da içerik olarak kullanılan sözlükleri döndürür.


Liste 13. Controller (denetleyici) sınıfı
from turbogears import controllers, expose

class Root(controllers.Root):

    @expose("tgcommerce.templates.category")
    def index(self):
	from model import Category
	category = Category.selectBy(parent=None)[0]
	return dict(category=category)

    @expose("tgcommerce.templates.category")
    def category(self, categoryID):
	from model import Category
	category = Category.get(categoryID)
	return dict(category=category)

TurboGears'ta, URL'ler yöntemlerle sorunsuz bir biçimde eşleşir ve Root (Kök) denetleyici içerisinde yer alır. Kök URL /, index adı verilen özel bir yöntemle eşleşir. Root'a category adlı bir yöntem ekleyerek, /category URL'si yoluyla buna erişilebilir. Bir default (varsayılan) yöntem tanımlı değilse, verilen bir yöntemle eşleşmeyen herhangi bir URL'nin sunulması 404 hatasına neden olur.

Aşağıda bazı olası URL senaryoları ve bunların sonuçları gösterilmiştir:

  • /: üst tanıtıcı olmadan ilk kategoriyi gösterir
  • /category?categoryID=2: 2 tanıtıcısına sahip kategoriyi gösterir.
  • /category/1: 1 tanıtıcısına sahip kategoriyi gösterir (bu biçim TG 0.9 ile sağlanmıştır)
  • /category: kategori tanıtıcısı olmadığı için bir 500 hatası gönderir.
  • /xyz: bir 404 hatası gönderir

Şekil 2 kategori görüntüleme sayfasını gösterir:


Şekil 2. Kategori görüntülenmesi
Kategori görüntülenmesi


Ürün görüntülenmesi

Ürün görüntüleme sayfası için, bir ürünü veritabanından alıp oluşturmak üzere bunu product Kid şablonuna geçiren bir product denetleyicisi yaratılır.


Liste 14. Ürün denetleyicisi yöntemi eklenmesi
@expose("tgcommerce.templates.product")
def product(self, productID):
    from model import Product
    product = Product.get(productID)
    return dict(product=product)

product.kid şablonunda ürün bilgileri tablosu bulunur. İki önemli basamağı olan bir fiyatı görüntülemek için Python dize biçimlendirmesinin kullanımına dikkat edin:


Liste 15. Kategori sayfası kid şablonu dosyası (product.kid)
<table id="product-info">
  <tr>
    <td class="fld">Name:</td>
    <td class="val"><span py:replace="product.name" /></td>
  </tr>
  <tr>
    <td class="fld">SKU:</td>
    <td class="val"><span py:replace="product.sku" /></td>
  </tr>
  <tr>
    <td class="fld">Price:</td>
    <td class="val">$<span py:replace="'%.2f' % product.price" /></td>
  </tr>
</table>

Şekil 3'te ürün görüntüleme sayfası gösterilir:


Şekil 3. Ürün görüntüleme sayfası
Ürün görüntüleme sayfası


Hata işleme

Denetleyici yöntemlerinin göz önünde bulundurmadığı nokta, SQLObject get yöntemleri tarafından gönderilen SQLObjectNotFound durumudur. Liste 16'da, bu olağandışı durumu yakalayan ve bunu bir NotFound (Bulunamadı) biçimindeki temel HTTP 404 hatası olarak yeniden gönderen bir yeniden yazma işlemi (refactoring) gösterilmiştir:


Liste 16. Controller sınıfına hata işleme eklendi
from model import Category, Product
from sqlobject import SQLObjectNotFound
from cherrypy import NotFound
from turbogears import controllers, expose, url

class Root(controllers.Root):

    @expose("tgcommerce.templates.category")
    def category(self, categoryID):
	try:
	    category = Category.get(categoryID)
	except SQLObjectNotFound:
	    raise NotFound()
	return dict(category=category)

    @expose("tgcommerce.templates.product")
    def product(self, productID):
	try:
	    product = Product.get(productID)
	except SQLObjectNotFound:
	    raise NotFound()
	return dict(product=product)

Eksik nesnelerin işlenmesi için bir 404 hatası göndermek yerine izlenen bir başka strateji de yeniden yönlendirmektir. Bu, turbogears.redirect(...) yöntemi kullanılarak gerçekleştirilir:


Liste 17. Yeniden yönlendirme örneği
from turbogears import redirect
try:
    object = ClassName.get(objectID)
except SQLObjectNotFound:
    raise redirect("/path_to_redirect")


Alışveriş sepeti

Çalışan bir alışveriş sepetinizin olması için, istekler arasında durumu korumak üzere oturumlarınızın etkinleştirilmiş olması gerekir. Oturumlar, yapılandırma dosyasında session_filter.on değerinin True olarak ayarlanmasıyla etkinleştirilir.


Liste 18. Yapılandırma dosyasında (dev.cfg) etkinleştirilen oturumlar
session_filter.on = True
sqlobject.dburi="notrans_sqlite:///path/to/devdir/TG-Commerce/tgcommerce.database"
server.environment="development"
autoreload.package="tgcommerce"

Geçerli alışveriş sepetini her bir sayfada görüntülemek için, HTML'yi her bir sayfaya kopyalayıp yapıştırmak yerine ana şablon dosyasına yerleştirebilirsiniz:


Liste 19. Ana kid şablonunda (master.kid) içerilen alışveriş sepeti
<html>
  <body>
  ...
	<div id="shopping-cart">
		Shopping Cart:
		<span id="cart-qty" py:content="cart.total_quantity" /> items
		($<span id="cart-amt" py:content="'%.2f' % cart.total_price" />)
	</div>
  </body>
</html>

Yukarıdaki şablon değişikliği tek başına başarısız olacaktır, çünkü denetleyici yöntemlerinden gelen dönüş sözlüklerinde bir cart değeri bulunmamaktadır. Liste 20'de, oturumda saklanmakta olan sepeti içerecek products yönteminde yapılacak değişikliği gösterir.


Liste 20. Denetleyicilerden dönen alışveriş sepeti nesnesi
@expose("tgcommerce.templates.product")
def product(self, productID):
    try:
	product = Product.get(productID)
    except SQLObjectNotFound:
	raise NotFound()
    return self.results(product=product)

def results(self, cart=None, **kw):
    if not cart:
	cart = self.get_cart()
    kw['cart'] = cart
    return kw

def get_cart(self):
    cartID = session.get("cartID", None)

    cart = None
    if cartID:
	try:
	    cart = Order.get(cartID)
	except SQLObjectNotFound:
	    pass

    if cart is None:
	cart = Order()
	session["cartID"] = cart.id

    return cart

results (sonuçlar) yöntemi, geçerli Order (Sipariş) nesnesini alacak ya da böyle bir nesne yoksa ya da bulunamazsa yenisini yaratacak olan get_cart'ı çağırır. Bu değişikliğin, index ve category yöntemlerinde de yer alması gerekir.



Ajax sepete ekle

Bu alışveriş sepeti örneğini teknik terimlerle açıklamak gerekirse, ürünü sepete ekle işlevi, sayfayı yenilemeksizin bir Ajax çağrısı yoluyla gerçekleştirilir. Konuya aşina olmayanlar için açıklamak gerekirse, Ajax, Asynchronous JavaScript + XML sözcüklerinin kısaltması olan (Zamanuyumsuz JavaScript + XML) bir Web uygulaması kalıbıdır. Ajax terimini ilk kez tanımlayan makale, Kaynaklar bölümünde listelenmiştir.

Bu örnekte, taşıma biçimi olarak XML yerine JavaScript Object Notation (JSON) kullanılmaktadır. JSON çok daha basittir ve hem TurboGears, hem de MochiKit tarafından yerel olarak desteklenir. Her ne kadar zamanuyumsuz JavaScript'in JSON ile kullanılması giderek daha da yaygınlaşıyorsa da, Ajaj kısaltması aynı derecede akılda kalıcı olmadığı için, bunun adı Ajax olarak kalacaktır.

Aşağıda, belirtilen ürünü alıp bunu oturumda geçerli olan sepete ekleyen add_to_cart (sepete ekle) denetleyici yöntemi gösterilmiştir. Yöntem, toplam fiyat ve sepetteki ürünlerin miktarıyla birlikte bu sepet nesnesini döndürür:


Liste 21. add_to_cart (sepete ekle) denetleyici yöntemi
@expose()
def add_to_cart(self, productID):
    cart = self.get_cart()

    product = Product.get(productID)
    cart.add_product(product, 1)

    return self.results(cart=cart,
	       price=cart.total_price,
	       quantity=cart.total_quantity)


expose yönteminin bir şablon adıyla birlikte sağlanmamış olduğuna dikkat edin. Bunun nedeni, yöntemin doğrudan bir tarayıcıdan çağrılacak ve HTML'de oluşturulacak olmamasıdır. add_to_cart sayfasını (http://localhost:8080/add_to_cart/1) doğrudan bir tarayıcıdan ya da curl gibi bir araç yoluyla görüntülerseniz, size işlenmemiş JSON verileri verilir: {"tg_flash":null, "price":24, "cart":{"id":24}, "quantity":1}.

İstemciden (tarayıcıdan) sunucudaki add_to_cart denetleyici yöntemine gelen JavaScript çağrısı çok basittir. MochiKit, bir URL'yi alıp deferred (ertelenmiş) olarak bilinen bir nesneyi döndüren ve loadJSONDoc olarak adlandırılan bir işlev sağlar. Bu ertelenmiş nesneyi, zamanuyumsuz çağrı bir yanıt döndürdüğünde bir geri arama yöntemi tanımlamak için kullanabilirsiniz.


Liste 22. Alışveriş sepeti AJAX mantığı (cart.js)
function addToCart(productID) {
	var deferred = loadJSONDoc('/add_to_cart/' + productID);
	deferred.addCallback(updateCart);
}

function updateCart(results) {
	$("cart-amt").innerHTML = numberFormatter("#.00")(results["price"]);
	$("cart-qty").innerHTML = results["quantity"];
}

Dönüşün ardından updateCart işlevine başvurulur ve results (sonuçlar) adı verilen çağrışımlı bir dizi değişkeniyle JSON değerleri sağlanır. İşlev tanıtıcıyı ve innerHTML özniteliğini kullanarak sepetin tutarını ve miktarını günceller. Bunun üzerinde, fiyata ilişkin önemli basamakları belirtmek için MochiKit numberFormatter işlevi kullanılır.

Bundan sonra en son adım, geçerli ürün tanıtıcısını geçirerek yukarıdaki addToCart işlevini çağıran bir bağlantı eklemektir. Ayrıca, MochiKit.js ve cart.js dosyalarınızı komut dosyası etiketleri olarak şablonunuza eklemeniz gerekir:


Liste 23. Add to cart (Sepete ekle) JavaScript çağrısının ürün sayfasına (product.kid) eklenmesi
<head>
    ...
    <script src="/tg_js/MochiKit.js" type="text/javascript" />
    <script src="/static/javascript/cart.js" type="text/javascript" />
</head>
<body>
    ...
    <table>
	...
		<tr>
			<td colspan="2" align="right">
				<a href="#" onclick="addToCart(${product.id})">Add To Cart</a>
			</td>
		</tr>
	</table>
</body>


Sonuç: TurboGears ile Django'nun Karşılaştırılması

Hem Django, hem de TurboGears, Python dilini kullanarak Web sitelerinin esnek ve hızlı bir biçimde geliştirilmesini sağlayan MVC biçimindeki çerçevelerdir. Gereksinimleriniz için en uygun olanı seçerken aşağıdaki farkları göz önünde bulundurun:

  • Geçmişe ilişkin bilgi:

    Her iki proje de, Ruby on Rails gibi, var olan uygulamalardan alındı ve açık kaynak topluluğuna yayınlandı. Django daha uzun zamandır piyasada ve ilk olarak günde milyonlarca sayfa görünümü sunan bir çevrimiçi gazeteden doğdu. TurboGears ise, hala geliştirilmeye devam eden zengin istemci RSS News Reader (Haber Okuyucu) uygulamasından doğdu. TurboGears, Django'ya göre topluluk tarafından daha fazla yönlendirilen bir çerçevedir, çünkü TurboGears var olan açık kaynak bileşenleri kullanılarak oluşturulmuştur.

    Her bir projenin farklı geçmişleri, bunların farklı proje önceliklerine sahip olmasına neden olmuştur. Yüksek talepli ve hızlı çevrimiçi gazetecilik dünyasından gelen Django ekibi, içeriğe dayalı uygulamaların hızlı bir biçimde oluşturulmasını ve kolayca değiştirilmesini sağlayan bir çerçeve üzerinde odaklandı. Tüketim malları temeline sahip TurboGears ekibiyse, zengin istemci uygulamalarına ve takılıp çıkarılabilen mimariye yöneldi.

  • URL'ler:

    TurboGears'ın istek dağıtma mekanizması, denetleyici sınıfı ve yöntem adları yoluyla yönlendirilir. Yeni bir denetleyici sınıfı ya da yöntemi eklediğinizde, eklenenler otomatik olarak kullanılabilir hale gelir. Belirli bir denetleyiciyi yürüten yolu değiştirmeniz gerekirse, kodunuzu yeniden yapılandırmanız gerekir. Bunun tersine Django, URL yolu yapısını gerçek kuruluştan ayırarak URL'leri temel kodla eşlemek için ayrı bir normal anlatıma dayalı yapılandırma dosyası kullanır.

    TurboGears sistemi, yeni sayfaların kullanılabilmesini sağlamak için yalnızca bir expose dekoratörünün varlığını gerektirdiğinden, Django'dan daha hızlı kurulur. Öte yandan, Django yapılandırma sistemi en üst düzeyde denetim ve esneklik sağlar. Django URL'leri, başlıca bir yeniden yazma işlemi (refactoring) sonrasında bir uygulamaya kolayca eklenebilir. Bu özellik, eski yer işaretleri ya da önbelleğe alınmış arama motoru sonuçlarının yol açtığı bağlantının bozulmasının (link rot) önlenmesine yardımcı olur. Bağlantı bozukluğu, Django'nun yaratması için tasarlanan içeriğe dayalı Web sitelerinin trafik düzeylerine ve kullanılabilirliğine ciddi zararlar verir.

  • Kodun yeniden kullanılması:

    TurboGears ekibi, TG'nin var olan bileşenlerden oluşturulan bir proje olduğunu açık bir biçimde belirtmek için projelerini megaframework (mega çerçeve) olarak adlandırır. TurboGears ekibi en baştan yazmak yerine kullanılabilir olan en iyi açık kodu seçer ve bütünleştirir. TurboGears çerçevesinin sağladığı bir yan avantaj da, mega topluluklu bir mega proje olmasıdır. TG, TurboGears'ı oluşturan çekirdek bileşenlere ilgi ve katılım isteği duyulmasını sağlayan güçlü, merkezi bir güç haline gelmiştir. O, bütün gemileri yükselten gelgittir.

    Diğer yandan Django, var olan Python bileşenlerinin henüz bugünkü kadar güçlü olmadığı 2003 yılında yaratılmıştı. Django Web yığını sıfırdan yaratıldı ve sonuç olarak günde milyonlarca ziyaretçi alan çeşitli Web sitelerini yaratmak için kullanılan sağlam bir çerçeve halini aldı. Ancak bazı kişiler, Django projesinin kodları yeniden kullanma özelliği olmadığı için NIH (Not Invented Here; Burada Keşfedilmedi) Sendromuyla karşılaşacağını ileri sürüyor. Django ekibinin konumunda, Python'da sıfırdan bir çerçeve yaratmak için yapılması gereken, var olan bileşenleri birbirine tutturmaktan daha zor değildir ve sonuçta daha bütün ve birörnek bir çerçeve yaratılır.

  • JavaScript:

    TurboGears, bir JavaScript kitaplığı olan MochiKit'e, çerçevesi bünyesinde birinci sınıf bir konum vermiştir. Ekip ayrıca "zengin" biçim öğeleri yaratmak amacıyla JavaScript'ten geniş biçimde yararlanan bir pencere bileşeni kitaplığı da yaratmıştır. Bu, TurboGears dünyasında bir zengin istemci (Ajax) geliştirmesinin ne kadar önemli olduğunu gösterir. Django ekibi, çerçevelerinde varsayılan değer olarak bir JavaScript kitaplığını içermeyi seçmemiş, ancak bu olasılığı tartışmıştır. Her iki proje de sizin JavaScript kitaplıklarını kullanmanızı hiçbir biçimde kısıtlamaz.

  • Yönetim araçları:

    Her iki projede de yönetim arabirimleri vardır. Django yönetim aracının hedef izleyicisi, bir uygulamaya her yeni işlev eklenmesinde özel araçların varlığını gerektirmeyecek, güzel görünümlü bir veri girişi aracına gereksinim duyan son kullanıcılardır. Diğer taraftan TurboGears yönetim aracı, temel bir veritabanı görüntüleyicisi ve düzenleyicisiyle birlikte bir tasarım araçları takımı sağladığı geliştiriciler üzerinde odaklanır.

  • Lisans:

    Django sıfırdan yaratıldığı için, projenin tamamı tek bir açık kaynak lisansı (BSD lisansı) kapsamındadır. Birden çok projeden oluşan TurboGears çerçevesinin çeşitli lisansları vardır. SQLObject, ORM aracı, LGPL'nin (Lesser General Public License) koruması altındadır ve buna göre, SQLObject kitaplığının kendi kaynak kodu değiştirilir ve dağıtılırsa, bu değişikliklerin herkes için sağlanması gerekir. Lisans, bunu kullanan uygulamaların açık kaynaklı olmasını gerektirmez. Yine de bazı firmalar, LGPL altında lisanslı bulunan yazılımın kullanılmasını engeller. Bu durumlarda, TG topluluğunda güçlü bir biçimde desteklenen bir başka ORM aracı olan SQLAlchemy aracını kullanmayı düşünebilirsiniz.

  • Gerçek dünyadan örnekler:

    Django ve TurboGears çerçeveleri tarafından desteklendiği bilinen siteleri listeleyen sayfalara ilişkin bağlantıları görmek için, Kaynaklar bölümüne bakın. Bu canlı uygulamalar, her bir araç ile neler yapılabileceğini gösterir.



Kaynaklar

Bilgi Edinme

Ürün ve teknoloji edinme
  • Python.org, Python yorumlayıcıyı ve standart kitaplıkları yüklemek için kullanılacak bağlantılara erişebileceğiniz Python programlama dili ana sayfasıdır.

  • TurboGears.com, TurboGears çerçevesinin ana sayfasıdır.

  • TurboGears önizleme sitesi, 0.9 alfa sürümünün geçerli ana sayfasıdır.

  • Kid, TurboGears için XML tabanlı bir şablon dilidir.

  • CherryPy, TurboGears çerçevesinin temelini sağlayan, Python ile uyumlu, nesne yönelimli bir Web çerçevesidir.

  • MochiKit, DOM ve Ajax desteği sağlayan, çok iyi sınanmış bir JavaScript kitaplığıdır.

  • JSON (JavaScript Object Notation), MochiKit ve TurboGears tarafından zamanuyumsuz ileti alışverişinde kullanılan basit bir veri değiş tokuşu biçimidir.

  • SEK for Linux ürününü sipariş edin. Bu ürün, DB2®, Lotus®, Rational®, Tivoli® ve WebSphere® üzerinde Linux için en güncel IBM deneme yazılımlarını içeren ikili DVD setidir.

  • Doğrudan developerWorks sitesinden yükleyebileceğiniz IBM deneme yazılımını kullanarak bir sonraki geliştirme projenizi Linux üzerinde oluşturabilirsiniz.


Tartışma


Yazar hakkında

Yazarın fotoğrafı: Ian Maurer

Brulant, Inc. şirketinde danışman müdür olarak çalışan Ian Maurer, tüketim malları ve perakende de dahil olmak üzere çeşitli sektörler için açık kaynak ve IBM WebSphere teknolojilerini kullanarak bütünleştirilmiş e-ticaret çözümleri geliştirme konusunda uzmanlaşmıştır. Ohio'nun kuzeydoğusunda yaşayan Ian, Cleveland Area Python Interest Group'un bir üyesidir.

İlgili Yazılar

developerWorks: Yüksek performanslı Linux kümeleme 2: Çalışan Bir Küme Oluşturma

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

Ajax Konusunda Uzmanlaşma, Bölüm 8

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

developerWorks: Linux için dokunmaya duyarlı ekran kurulması

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan ikinci IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

developerWorks: Yüksek performanslı Linux kümeleme - 1: Kümelemenin İlkeleri

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

UNIX Dilinde Konuşma, Bölüm 5: Veriler, veriler her yerde!

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.