.. meta:: :description: Bu bölümde tornado ile web uygulaması geliştirmeye başlıyoruz. :keywords: python, tornado, Kurulum, Proje Oluşturma, View, Template .. highlight:: python3 ******* Tornado ******* Eğer yazdığınız sitede gerçek zamanlı(real-time) bağlantılar kullanacaksanız ya da bir mikro çerçeveye(micro framework) ihtiyacınız varsa tornado tamamen sizin ihtiyaçlarınız için tasarlanmış bir çerçeve. Kurulum ======= Tornado'yu kullanmak için önce indirmemiz gerekiyor. Aşağıdaki komutu komut istemcisinde yazın:: pip install tornado `Successfully installed tornado-6.1` yazısını gördüyseniz sorunsuzca inmiştir. Proje Oluşturma =============== Tornado, herhangi bir dizinde açtığınız herhangi bir dosyada çalışabilir. Yani normal bir python dosyası açalım ve yazmaya başlayalım. Ben `torn` isimli bir klasör açıp `__init__.py` dosyasında yazacağım. Önce dosyanın ana bileşenlerini yazalım:: import tornado.web import tornado.ioloop app = tornado.web.Application() app.listen(8888) tornado.ioloop.IOLoop.current().start() Hemen burada ne yaptığımızı açıklayalım. Önce kullanacağımız modülleri içeri aktardık:: import tornado.web import tornado.ioloop Daha sonra bir sitemizi çalıştırmak için gerekli ayarları yaptık:: app = tornado.web.Application() # İleride yönlendirme(routing) için kullanacağımız araç. app.listen(8888) # Port olarak 8888 belirledik. Siz başka bir sayı seçebilirsiniz. tornado.ioloop.IOLoop.current().start() # Sitemizi çalıştırmaya başladık Sitemizi açmak için önce yazdığımız dosyayı çalıştıralım. Daha sonra `http://localhost:8888/` adresine gidelim. Elbette farklı bir port seçtiyseniz portu değiştirmeyi unutmayın. Siteye girdiğiniz zaman sizi `404: Not Found` yazısı karşılayacak. Çünkü daha hiç sayfa oluşturmadık. Hadi şimdi bir sayfa oluşturalım. Sayfa Sunma =========== Sitemizde sayfa sunmak için bir view yazmalıyız. Geleneği bozmayalım ve "Merhaba Zalim Dünya" yazarak başlayalım. Bu iş için `Application`'da olduğu gibi `tornado.web` modülünü kullancağız. Bu sefer `RequestHandler` isimli bir sınıf bize yardımcı olacak. Şimdi yazacağımız kodları içe aktarma ile `app` değişkeni arasına yazalım:: class Merhaba(tornado.web.RequestHandler): # View için bir sınıf oluşturduk def get(self): # Sayfayı yollayan fonksiyonumuz self.write("Merhaba, Zalim Dünya!") # En basit yolu kullanarak "Merhaba, Zalim Dünya!" yazdık İlk viewımızı yazdık. Şimdi dosyamızı tekrar çalıştırıp test edelim. Sonuçta bir değişiklik olmadığını göreceksiniz. Yani hâlâ `404: Not Found` yazıyor. Çünkü sitemize gelen istekle view arasındaki bağlantıyı kurmadık. Hadi hemen yapalım. Kullanıcının siteye girmesiyle sunucuya bir istek yollanır. Bu istek kullanıcının adres çubuğuna yazdığı ifadeyle doğrudan ilişkilidir. Mesela kullanıcı `http://localhost:8888/istihza/` yazarsa bizden `/istihza/` adresini istemiştir. Eğer biz bu adresi bir view ile ilişkilendirdiysek bu view çalışır. Eğer ilişkilendirmediysek `404` hatası alırız. Biz `Tornado`'da bu ilişkilendirme işini `Application`'dan faydalanarak yapıyoruz. Yani `app = tornado.web.Application()` diye yazdığımız bölümü düzenleyeceğiz:: app = tornado.web.Application([ ("/", Merhaba) ]) Şu an `/` isteği ile `Merhaba` viewı arasında bir ilişki kurduk. Nasıl yazdığımıza dikkat edelim: Bir liste içinde önce istek sonra view içeren bir demet. Eğer daha fazla view eklemek isterseniz aynı liste içine demet ekleyerek yapabilirsiniz. `http://localhost:8888/` adresine giderek `Merhaba, Zalim Dünya!` yazdığını görebiliriz. Yazdığımız kodları topluca paylaşayım:: import tornado.web import tornado.ioloop class Merhaba(tornado.web.RequestHandler): # View için bir sınıf oluşturduk def get(self): # Sayfayı yollayan fonksiyonumuz self.write("Merhaba, Zalim Dünya!") # En basit yolu kullanarak "Merhaba, Zalim Dünya!" yazdık app = tornado.web.Application([ ("/", Merhaba) ]) app.listen(8888) tornado.ioloop.IOLoop.current().start() Template(Şablon) Sistemi ======================== Sitemizde göstereceğimiz sayfaları `html` formatında yazıp kaydetmeliyiz. Daha sonra bu dosyaları `Tornado` ile çağırıp servis etmeliyiz. Göstereceğimiz sayfalar ikiye ayrılıyor: "Statik" ve "Dinamik". Statik sayfalar `Tornado`'nun çağırıp değiştirmeden servis ettiği dosyalardır. Dinamik sayfalar ise `Tornado`'nun çağırdıktan sonra düzenleyip servis ettiği dosyalardır. Önce bir `html` dosyası oluşturalım, ardından bu dosyayı servis edelim. .. code-block :: Merhaba Zalim Dünya

Merhaba Zalim Dünya

Bu dosyayı "`index.html`" ismiyle `torn` klasörüme kaydedeceğim. Siz başka bir isimle başka bir klasöre de kaydedebilirsiniz. Hemen servis etmek için `Merhaba` `view`'ını düzenleyelim:: class Merhaba(tornado.web.RequestHandler): def get(self): loader = tornado.template.Loader(".") sayfa = loader.load("index.html").generate() self.write(sayfa) Ben servis etmek için `Merhaba view`'ını düzenlemeyi tercih ettim. Ancak siz yeni bir `view` yazmak isteyebilirsiniz. Bu durumda yazdığınız `view`'ı yeni bir istek ile eşleştirmeniz gerekir. Bu iş için de bir örnek verip kodlarımızı açıklayayım. Oluşturduğunuz `view`'ın adı `Yazbel` olsun ve `/yazbel/` isteği ile ilişkilendirelim:: app = tornado.web.Application([ ("/", Merhaba), # Buradaki virgülü koymayı unutmayınız ("/yazbel/", Yazbel) ]) Bu durumu geçip yukarıdaki kodlara tekrar bakalım. İlk satırda eklediğimiz kod:: loader = tornado.template.Loader(".") Burada `Html` dosyalarımızın bulunduğu dizini `Tornado`'ya bildirdik. Eğer `Html` dosyalarınız farklı bir dizinde yer alıyorsa benim `.` yazdığım yeri o dizin ile değiştirmelisiniz. Peki neden bildirdik? Çünkü web programlamada `Html`, `Css`, `Js`, `Resim` gibi dosyalar kendilerine ait bir klasörde bulunur. Biz `Html` dosyalarının bulunduğu klasörü bildirerek tekrar tekrar yazmaktan kurtulduk. İkinci eklediğimiz satıra bakalım:: sayfa = loader.load("index.html").generate() Burada daha önce oluşturduğumuz `loader` değişkenini kullanarak sayfamızı getirdik. `generate` fonksiyonunu kullanarak sayfayı `Tornado`'nun sunabileceği bir hale dönüştürdük. Daha sonra `write` fonksiyonuyla sayfamızı gösterdik:: self.write(sayfa) Şimdi de dinamik sayfaların nasıl oluşturulduğuna bakalım. Dinamik sayfaların çağrıldıktan sonra düzenlendiğini söylemiştik. Düzenleyeceğimiz yeri `Tornado`'ya bildirmek için `Template`(Şablon) denen bir yöntemden faydalanacağız. Değişiklik yapmak istediğimiz yeri 2 tane küme parantezi içinde bir isimle `Html` dosyamızda kullanıyoruz. Hemen bir `index.html` dosyasını düzenleyerek bir örnek verelim. .. code-block :: Merhaba {{ yazbel }}

Merhaba {{ yazbel }}

Burada `{{ yazbel }}` yazarak `yazbel` isimli bir değişken tanımladık. Tabi ki siz farklı bir değişken isimi seçebilirsiniz. Şu an `__init__.py` dosyamızı çalıştırıp `http://localhost:8888/` adresine gidersek `500` hatasıyla karşılaşacağız. `__init__.py`'nin çalıştığı komut istemcisine bakarsak bir hata göreceğiz. .. code-block :: NameError: name 'yazbel' is not defined Bu hatadan `yazbel` isimli bir değişken tanımlayıp ona bir değer vermediğimiz için karşımıza çıktı. Bu değişkene değer vermek için `generate` fonksiyonunu kullanacağız:: sayfa = loader.load("index.html").generate(yazbel="Yazbel") `__init__.py` dosyasını tekrar çalıştırdığımızda `Merhaba Yazbel` yazısıyla karşılaşacağız. Aklınıza şöyle bir soru takılmış olabilir: Bu şekilde yapmak yerine `Html` dosyasını düzenlemek daha kolay olmaz mı? Elbetteki olabilir ancak aynı işi yapan birkaç view daha yazdığımızda birkaç `Html` dosyası daha oluşturmamız gerekir. Mesela sitemize şu iki `view` da katıldığında dinamik olarak oluşturmak daha mantıklı oluyor:: class Merhaba_istihza(tornado.web.RequestHandler): def get(self): loader = tornado.template.Loader(".") sayfa = loader.load("index.html").generate(yazbel="İstihza") self.write(sayfa) class Merhaba_Dünya(tornado.web.RequestHandler): def get(self): loader = tornado.template.Loader(".") sayfa = loader.load("index.html").generate(yazbel="Dünya") self.write(sayfa) `Template` sisteminde kullanabileceğimiz bir özellik daha var:`if`, `else`, `else`, `for`. Fakat bu özelliği 2 küme işareti arasında değil 1 küme 1 yüzde işareti arasında kullanıyoruz: `{% else %}`. Bu özelliği anlatma için listelerden faydalanalım. `Merhaba` viewımızı `yazbel` değişkenine bir liste verecek şekilde düzenleyelim:: class Merhaba(tornado.web.RequestHandler): def get(self): loader = tornado.template.Loader(".") liste = [0, 1, 2, 3] sayfa = loader.load("index.html").generate(yazbel=liste) self.write(sayfa) Hemen bu sayıları listeleyecek bir `Template` (Şablon) yazalım. Bu listede çift sayılar büyük, tek sayılar küçük gözüksün. .. code-block :: {% for sayı in yazbel %} {% if sayı%2==0 %}

{{ sayı }}

{% else %}

{{ sayı }}

{% end %} {% end %} Gördüğünüz gibi genel olarak `python` ile çok benzer bir yapıya sahip ancak çok önemli bir fark var. `for` döngüsü bir `end` ifadesiyle bitiyor. Aynı şekilde birbiriyle ilişkili kontrol ifadeleri(`if`, `else`) hep birlikte bir `end` ile bitiyor.