24 Aralık 2014 Çarşamba

Pebble ile Libreoffice Impress Uzaktan Kontrolü


    Libreoffice üzerinde sunumlarınızı yaparken slaytı değiştirmek için yeniden bilgisayarın başına mı gitmeniz gerekiyor? Ya da bu işi uzaktan yapmak için elinizde kocaman bir telefon mu taşımak zorunda kalıyorsunuz? Durun! Artık slaytlarınızı Pebble ile değiştirebilirsiniz... Nasıl mı? :D

    1) Pebble'ınızın telefonunuzla olan bağlantısını kesin.

    2) Pebble'ı bilgisayarınızın bluetoothu ile eşleştirin. Pebble sürekli dışarıya görünür halde olmadığından bu eşleşmeyi yapmak için biraz hızlı olmanız gerekecek. Pebble'ın dışarıya görünür hale gelmesi için  Settings-->Bluetooth ayarına girdiğinizde yukarıda "Now Discoverable" yazısı çıkacaktır. O anda bu eşleşmeyi yapmak gerekiyor. Bir defada olmayabilir. Bu kısım bi miktar sıkıntılı ancak bunu sadece bir kez yapmanız yeterli. Siz elle bu eşleşmeyi bitirmediğiniz sürece bir daha böyle bir işlemeye ihtiyaç olmayacaktır.

    3) pebble-remote uygulamasın indirin. Sıkıştırılmış bir şekilde indirebilirsiniz ya da şu komutu kullanarak uygulamayı klonlayabilirsiniz.

        $ git clone  https://github.com/COMU/pebble-remote

    4) Bağımlılıkları kuruyoruz.

        $ sudo apt-get install python-dev libopenobex1-dev python-tk python-lightblue python-pexpect xdotool python-bluez

     5) lightblue-0.4 uygulamasını indirip kuruyoruz:

        $ git clone https://github.com/pebble/lightblue-0.4/
          $ cd lightblue-0.4
          $ sudo python setup.py install

    6) Bir terminal aracılığıyla pebble-remote dizini içine geçin:
     
        $cd /path/to/pebble-remote

    7) Burada çalıştırmak için gerekli komutu yazarken bazı parametrelere ihtiyacınız olacak.

Birinci parametre pebble id Bu bilgiyi iki şekilde öğrenebilirsiniz. Birincisi Pebble üzerinde Settings-->About-->BT Address

İkincisi bilgisayarınızda bluetooth ayarlarında eşleşmiş cihazlara girip Pebble cihazına tıkladığınızda sağ tarafta adres bilgisi olacaktır.

Adres 6 oktetten oluşan 11:22:33:AA:BB:CC gibi bir bilgidir. Bu bilgiyi bir kenara not edelim.

İhtiyacımız olan ikinci parametre, yapmak istediğiniz sunumun bilgisayardaki tam yolu.
Örneğin: /home/gulsah/sunum1.odp

Artık  şu komutu çalışırabiliriz(Kendi pebble id niz ve sunumunuzun tam yolu ile):

./p.py --pebble_id 11:22:33:AA:BB:CC --lightblue remote libreoffice /home/gulsah /sunum1.odp

    Bu komutu çalıştırdıktan sonra pebble ile bağlantıda bir sorun yaşarsanız bir defa bu komutu çalıştırırken yine pebble'ın ikinci adımda tarif ettiğim gibi görünür olması gerekebilir.

    Sunum önünüze tam ekran açılacaktır. Pebble içindeki müzik uygulamasını açıp üst ve alt düğmelerini kullanarak slaytlarınızı Pebble ile değiştirebilirsiniz. :)

 


1 Eylül 2014 Pazartesi

cesi (Centralized Supervisor Interface)

    Supervisor had an interface but there were some shortcomings in the existing interface. Some shortcomings in the existing interface :

    -- Interface allows process management where supervisor's installed on computers but API allows management remote computers's process.

    -- No authorization. Anyone who can see the interface can do what you want.

    -- Process management were made without filters.

    I did my internship this summer with Kaan at Gamegos. We wrote an interface that complement these deficiencies. We use Python Flask and Jquery. I did not pack for now. I've described how to install at README. I'll explain the use of the interface on this blog.

    You can find the project here

  DASHBOARD
--------------------------

    This page is the first page you will see when the program runs. We can see that the total number of nodes , number of connected nodes and number of not connected nodes. Also we can see total number of process , number of running process, number of stopped process and the last 12 lines of activity log.













    NODE
----------------
 
    Node is a feature that provides be central of this interface. Each node corresponds to a different supervisor that we contacted. We should write into /etc/cesi.conf host port username and passwors information of every supervisor that we want to connect. (Node names must be unique.):

  [node:gulsah]
 username = gulsah
 password = ***
 host = gulsah.xyz.com
 port = 9001
    
     A list opens when we click on the node. This list is a list of nodes in the configuration file. If connected node node name must be the beginning of a checkbox. If there is a problem with the connection at the beginning of the node name will be an "x". We can manage the processes of selecting the node we want.


   ENVİRONMENT
----------------------------

    Environments are communities of nodes. It is a filtering option.This option provides stop start or restart process that environment name x and node name y. We can define the environment as much as we want. Environment names must be unique.

  [environment:market]
  members = gulsah, kaan

     A list opens when we click on the environmet. This list is a list of environments in the configuration file. When clicked an environment opens a list that include nodes that connected and members of that environment . We can manage the processes of choosen nodes.











  GROUP
---------------


   Group is a feature that already exists in the program. We don't need write in /etc/cesi.conf  . It is a filtering option provides stop start or restart process that group name x and environment name y.

    When clicked group option, opens a list that groups. When clicked a group opens a list of environment which include that group name.

  *The same process must not belong to more than one group.










 



 SHOW ALL
---------------------

    Show all option provides manage all node's processes.




















     We can subselection on tables. We can checked begin of process. By clicking the button above the table, action runs for checked process.


    We must write database and activity log path into /etc/cesi.conf before programs running.

    [cesi]
    database = /x/y/userinfo.db
    activity_log = /x/y/cesi_activity.log


   USER LEVEL
-------------------------

   Admin:
   -- Only admin can add or delete a user. They can do everything related to all process.

  Standart User:
   -- Standart users can't delete or add user but can everything else.

  Only Log
  -- Only log users can view process and read processes logs.

  Read Only
  -- Read only users only can view processes.




    When program run first time default username and password are "admin". Admin change own password using by change password option. If necessarily admin can add a user what type you want. when new users logged in,  they can change own password by change password options.


User addition panel:    
















User deletion panel:



Thanks to Kaan Özdinçer for support.






29 Ağustos 2014 Cuma

cesi (Centralized Supervisor Interface)


    Bir önceki yazımda Supervisordan bahsetmiştim. Supervisor arayüzden de komut satırından da kullanılabilen bir API si olan Unix benzeri işletim sistemleri üzerinde çalışan bir süreç yönetim sistemidir. Bazı eksikleri şöyleydi:

  -- Supervisorun varolan arayüzü sadece kurulu olduğu makine üzerindeki süreçleri yönetebiliyordu. Ama API uzaktaki makinelerle iletişim kurmaya izin veriyordu.
  -- Arayüzde herhangi bir yetkilendirme seviyesi yoktu. Arayüzü görebilen herkes süreçlerle ilgili istediğini yapabiliyordu.
  -- Herhangi bir şekilde süreçler filtrelenerek yönetilemiyordu. Ya tek tek ya da hepsiyle birden iş yapılabiliyordu.

    Bu yaz stajımı Gamegos'ta Kaan'ın mentörlüğünde yaptım. Yaptığımız iş Supervisor'a yukarıda bahsettiğim eksiklikleri gideren yeni bir arayüz yazmaktı. Yeni arayüzü Python Flask ve Jquery kullanarak yazdık. Şimdilik paketlemedim. Nasıl kurulacağını projenin README kısmında açıkladım. Bu blogta arayüzün yeteneklerini ve kullanımını anlatacağım.
  Projeyi buradan bulabilirsiniz.

  DASHBOARD
--------------------------

    Program çalıştığında karşımıza gelen ilk sayfadır. Toplamda kaç node olduğunu kaçının bağlı kaçının sorunlu olduğunu, toplam kaç süreç olduğunu kaçının çalışıp kaçının durmuş olduğunu ve kullanıcının arayüzde yaptığı işlemlerin logunun son 12 satırını görüntüleyen paneller var.













    NODE
----------------
   
    Node özelliği bu arayüzün merkezi olmasını sağlayan özelliktir. Yani her bir node bizim iletişim kurduğumuz farklı bir supervisora denk geliyor. Kaç tane süpervisor ile iletişim kuracaksak hepsinin host port kullanıcı adı parola bilgilerini /etc/cesi.conf içine şu şekilde yazmalıyız (node isimleri eşsiz olmalıdır) :

  [node:gulsah]
 username = gulsah
 password = ***
 host = gulsah.xyz.com
 port = 9001
    
     Node seçeneğine tıkladığımızda açılan liste yapılandırma  dosyasındaki nodeların listesidir. Node eğer bağlıysa node  isminin  başında bir checkbox olacaktır. Bağlantıda bir  problem  olmuşsa node isminin başında bir çarpı olacaktır.  Buradan istediğimiz nodeları seçerek süreçlerini  yönetebiliriz.


   ENVİRONMENT
----------------------------

    Nodelardan oluşan topluluklardır. Bir filtreleme seçeneğidir. Environment'ı x node ismi y olan süreçler hakkında şunları yap dememize imkan tanır. İstediğimiz kadar environment tanımlayabiliriz. Environment isimleri eşsiz olmalıdır. /etc/cesi.conf  dosyasında şöyle tanımlanır:

  [environment:market]
  members = gulsah, kaan

  Arayüzde environment seçeneğine tıkladığımızda o environmenta üye olan ve bağlantısında problem olmayan nodeların listesini görürüz. Bu nodelardan hangisini seçersek onların süreçlerini yönetebiliriz.











  GROUP
---------------


   Grup zaten Supervisor'un sağladığı bir özellikti. Bu yüzden /etc/cesi.conf içine bununla ilgili birşey yazmaya gerek yok. Supervisor'un yapılandırma dosyasında tanımlanır. Süreçler bir gruba eklenebilir. Eğer sürecin grubu yoksa varsayılan olarak grup adı sürecin adı olur. Bu da arayüzde bir filtreleme seçeneğidir. Grubu x environmeti y olan süreçler için şunları yap deme imkanı sağlar.

    Arayüzde grup seçeneğine tıkladımızda içinde o grubu bulunduran  environmetların listesini görürüz. Buradan hangi environmentleri seçersek grubu seçtiğimiz grup, environmenti seçtiğimiz environment olan süreçleri görüntüleyip yönetebiliriz.

  *Aynı süreç birden fazla gruba ait olmamalıdır.










  SHOW ALL
---------------------

Show all seçeneği ne kadar node ve onların ne kadar süreci varsa hepsini birden görüntülemeyi ve yönetmeyi sağlar.




















    Ayrıca herhangi bir şekilde görüntülediğimiz tabloların üzerinde alt seçimler de yapabiliriz. O anda görüntülediğimiz süreçlerden hangisinin başındaki checkbox işaretliyse tabloların üstündeki turuncu butonları kullanarak sadece o süreçleri durdurup başlatabiliriz.


    Program çalıştırılmadan önce yapılandırma dosyasında veritabanı ve kullanıcı loglarının tutulduğu dosyaların yolunu /etc/cesi.conf dosyasında şu şekilde belirtmeliyiz:

    [cesi]
    database = /x/y/userinfo.db
    activity_log = /x/y/cesi_activity.log


   KULLANICI SEVİYELERİ
--------------------------------------------

   Admin:
   -- Kullanıcı ekleme silme işi sadece admin tipindeki kullanıcılar tarafından yapılır.
   -- Tüm süreçlerle ilgili herşeyi yapabilirler.

  Standart User:
   -- Tüm süreçler hakkında herşeyi yapabilir.

  Only Log
  -- Süreçlerin hepsini görüntüleyebilir
  -- Süreçlerin sadece loglarını okuyabilir.

  Read Only
  -- Sadece süreçleri görüntüleyebilir. Herhangi bir şeye müdahale edemez.




    Program ilk kurulduğunda varsayılan kullanıcı admindir. Kullanıcı adı ve parolası "admin" dir. Change password seçeneğini kullanarak admin ilk olarak parolasını değiştirmelidir. Gerek varsa istediği yetkilerde yeni kullanıcılar ekleyebilir. Eklediği yeni kullanıcılarda oturum açtıklarında aynı şekilde parolalarını değiştirebilirler.


Kullanıcı ekleme paneli:      
















Kullanıcı silme paneli:



Desteği için Kaan Özdinçer'e teşekkürler. 







3 Temmuz 2014 Perşembe

Supervisor

  Supervisor kurulu olduğu bilgisayarın üzerindeki süreçleri kontrol edebilen Unix benzeri işletim sistemleri üzerinde çalışabilen bir sistemdir. Aslında süreçlerin kontrolünü rc.d dizini altına betikler yazarak da yapmak mümkün ama supervisor bu işi bi standarta göre yaptığından bakım yapmak da yazmak da yönetmek de daha kolay olacaktır. Ayrıca süpervisor ile zombi süreç oluşumunu engelleyebiliyoruz. Süreçleri gruplayarak toplu işler yaptırabiliyoruz. Tek seferde birden çok sürece parametre gönderebiliyoruz. Duran süreçleri otomatik başlatabiliyoruz. Hepsinden sırayla bahsedeceğim.

  Arayüzünün görünümü ise şöyle:


















   Komut satırını kullanarakta bilgi almak mümkün. Komut satırına supervisorctl yazarak etkileşimli bir kabuk açıldığını göreceğiz. "help" yazdığımızda yapabileceklerimizi rahatlıkla görebiliriz.

   Kurulumu:
  "easy-install supervisor", "pip install supervisor" kullanmak ya da direk kaynak kodundan kurmakta mümkün ama depodan kurabiliyor olmak kullanım alanını genişletecektir. Bu yüzden bunu tercih ediyoruz.

$ sudo apt-get install supervisor

  Şuan varsayılan olarak /etc/supervisor/supervisord.conf yolunda şablon olarak bir yapılandırma dosyası oluşmuş olmalı. İşler karmaşıklaştığında yönetimin daha kolay olması için buradaki bazı bölümleri yavaş yavaş /etc/supervisor/conf.d/ dizini altına taşıyacağız. İlk olarak http yaplandırması kısmını şöyle yazıyoruz:

  # vim /etc/supervisor/conf.d/http.conf

Açılan dosyaya şu yapılandırma bilgierini ekeyelim:

  [inet_http_server]         ; inet (TCP) server disabled by default
  port=*:9001        ; (ip_address:port specifier, *:port for all iface)
  username=user              ; (default is no username (open server))
  password=123               ; (default is no password (open server))

2. satırda * yerine özel bir ip adresi ya da localhost yazabiliriz. * yazmamız supervisor'a tüm arayüzlerden ulaşabilmemizi sağlar. Bu dosyayı kaydedip çıkalım.

  İçinde şuan kayıtlı hiçbir süreç olmadığından çalıştığında bir süreç göremeyeceğiz. Çalıştırmak için şu komutu verelim:

  # service supervisor start

  Şimdi adres çubuğuna localhost:9001 yazdığımızda yukarıdaki resmin süreçler olmadan ki halini görüyor olmamız lazım

  Şimdi hiçbirşey yapmayan örnek bir kod yazalım supervisor'a ekleyelim ve durumunu inceleyelim:

  # vim /usr/local/bin/long.sh

  Açılan dosyaya şu kodu yazalım:

  #!/bin/bash
  while true
  do
      # Echo current date to stdout
      echo `date`
      # Echo 'error!' to stderr
      echo 'error!' >&2
      sleep 1
  done

  Kaydedip çıkalım ve şimid bu dosyaya çalıştırılabilme izni verelim:

  # chmod +x /usr/local/bin/long.sh

   Şimdi yazdığımız bu küçük programı supervisor 'un yapılandırmasın ekleyelim.

  # vim /etc/supervisor/conf.d/long_script.conf 

  Açılan dosyaya şunalrı yazalım:

   [program:long_script]                       ; programa verecğimiz isim
   command=/usr/local/bin/long.sh       ; eklemek istediğimiz kodun yolu
   autostart=true                                    ; supervisor çalıştığında otomatik başlatılıp başlatılmayacağı
   autorestart=true                                 ; otomatik yeniden başlatılıp başlatılmayacağı
   stderr_logfile=/var/log/long.err.log   ; standart hata çıktısının yazılacağı dosyanın yolu
   stdout_logfile=/var/log/long.out.log  ; standart çıktısının yazılacağı dosyanın yolu

 Bu dosyayı kaydedip çıkalım. Bu yaptığımız değişiklikleri okuyabilmesi için supervisor'u yeniden başlatalım:

  # service supervisor restart

  Şimdi adres çubuğuna yeniden localhost:9001 yazdığımızda bir tane satır görüyor olmamız gerekiyor.

  Programla ilgili şu bilgileri göreceğiz:
  Durumu:
      --running
      --starting
      --backoff
      --stopping
      --stopped
      --exited
      --fatal

  Süreç numarası:

      --pid 1800

  Sürecin çalıştığı süre:

     --uptime 3:24:07

  Adı:

    --long_script

  Ve bu süreç üzerinde yapabileceğimiz olaylar:   Yeniden başlat, başlat, durdur, logları temizle, logları görüntüle gibi

   Bir sonraki yazımda XML-RPC API sinin kullanımından API yi kullanarak süreçlere nasıl müdahale edebildiğimizden  bahsedeceğim.

27 Haziran 2014 Cuma

Bootstrap



  Bootstrap web uygulamalarımızı ekran boyutundan bağımsız bir şekilde yazmamızı sağlayan bir çatı. Yani uygulamayı tek bir web çatısı kullanarak yazıyoruz ve küçük ekran telefonlardan geniş ekran bilgisayarlara kadar her yerde görünümü bozulmadan kullanabiliyoruz. Bu yazımda bir önceki yazımda Flask ile yazdığım basit blog uygulamasının Bootstrapla iyileştirilme aşamalarını anlatacağım.

  Bootstrap'ın Flask için yazılmış bir modülüde mevcut "pip install flask-bootstrap" diyerek kurup öyle kullanılıyor.  Ama bunu kullanmak yazacağımız uygulamanın kullanım alanını daraltabilir. Örneğin eğer uygulama kararlı depoyu kullanan bir sunucu yada bilgisayarda kullanılacaksa yazacağımız uygulamayı buralarda kullanmak istemeyeceklerdir.

  Bootstrap'ın çok fazla bileşeni olduğundan sadece bloğumuz için gerekli olanlardan bahsedeceğim daha ayrıntılı bilgiyi buradan bulabilisiniz.

  Bootstrap'ı uygulayacağımız blog uygulamasını buradan bulabilirsiniz.

*  Öncelikle linkten Bootstrap için gerekli dosyaları indirmeliyiz. İndirdiğiniz dosyayı açarak uygulamamızın içindeki static dizini altına taşımalıyız.

*  .../templates/layout.html dosyasının başına şu satırı ekleyerek kullanacağımız css dosyasının yolunu belirtmiş oluyoruz:

     <link rel=stylesheet type=text/css href="{{ url_for('static', filename='bootstrap-3.1.1-\
dist/css/bootstrap.min.css') }}">

*  Şimdi bootstrap'ın  her ekran boyutunda düzgün görünmesini sağlayan layout özelliğini ekleyeceğiz. Bootstrap uygulamamızı 12 kolon'a kadar ölçekleyebilir. Biz ekranımızı şekilde görüldüğü gibi bölerek orta kolonu kullanacağız.

  Bunun için Bootstrap içindeki .col-md-* sınıfını kullanacağız. Daha küçük ekranlardaki görünümü için .col-xs-* sınıfını kullanacağız. Yine layout.html dosyasına şu kodu ekleyeceğiz:

<div class="row">
  <div class="col-md-4"> İlk bölme </div>
  <div class="col-xs-12 col-md-4"> Orta bölme </div>
  <div class="col-md-4"> Son bölme</div>
</div> 

*  İlk ve son bölmeyi boş bırakacağız. Orta bölmeye kodun layout kısmını içinde kullanıcıya göstereceğimiz kısmı koyacağız. 

* Aynı yerde "log in" ve "log out " butonlarınıda iyileştirmek için  butonların bulunduğu satırı şu şekilde değiştirelim:

 <a class="btn btn-primary btn-lg" role="button" href="{{ url_for('login') }}">log in</a>
 <a class="btn btn-primary btn-lg" role="button" href="{{ url_for('logout') }}">log out</a>

*  .../template/login.html dosyasını açalım ve oradaki kullanıcı adı ve parola kısımlarını ve submit butonunun görünümünü Bootstraptaki sınıfları kullanarak iyileştirmek için form etiketleri arasını aşağıdaki kod ile değiştirelim.

<form action="{{ url_for('login') }}" method=post role="form">
  <div class="form-group">
    <label for="exampleInputEmail1">User name</label>
      <input type="text" name="username" class="form-control"  placeholder="Enter user name please">
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Password</label>
      <input type="password" name="password" class="form-control" placeholder="Enter password please">
  </div>
  <div class="metanav">
      <button type="submit" class="btn btn-primary btn-sm">Submit</button>
  </div>
  </form>

*  .../template/show_entries.html dosyasını açalım Yine aynı şekilde formun ve butonların görünümünü iyileştirmek için aşağıdaki form etiketleri içindeki kodu aşağıdaki kod parçasıyla değiştirelim.

  <form action="{{ url_for('add_entry') }}" method=post role="form">
    <div class="form-group">
      <label>Title</label>
        <input type="text" name="title" size=30 class="form-control"  placeholder="Enter title please">
    </div>
    <div class="form-group">
      <label>Text</label>
        <textarea name="text" row=5 cols=40 class="form-control" placeholder="Enter password please"></textarea>
    </div>
    <button type="submit" class="btn btn-primary btn-sm">Submit</button>
  </form>

* Aynı dosya içinde daha önce yazılmış bloglar liste şeklinde görünüyordu. Onların göürünümünü iyileştirmek için tablo kullanmayı tercih ettim. O kısmıda şu şekilde değiştirebiliriz:

<table class="table table-hover">
{% for entry in entries %}
  <tr class="info text-center"><td><h3>{{ entry.title }}</h3>{{ entry.text|safe }}</td></tr>
{% else %}
  <tr class="info text-center"><td><em>Unbelievable. No entries here so far</em></td></tr>
{% endfor %}
</table>

  Artık dosyayı kaydedip bloğu çalıştırdığımızda pencere küçülterek görüntünün bozulmadığını ve bloğun eskisinden daha iyi göründüğünü görebiliriz.

Ek olarak:

  Belki ileride işimiz yarayabilecek bir bileşen "navbar" bileşeni. Hızlıca nasıl çalıştığını layout.html dosyasının başına şu kodu eklediğimizde hızlıca görebiliriz:

<div>
  <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
  </nav>
</div>



23 Haziran 2014 Pazartesi

Flask ile Blog Uygulaması





Önceki yazımda Flask'ın kurulumunu anlatmıştım. Şimdi Flask kullanarak basitçe bir blog nasıl yazılır adım adım anlatmaya çalışacağım.

  $ mkdir flaskr
  $ cd flaskr
  $ vim schema.sql

  Açılan dosya içine şu satırları ekleyelim:

  drop table if exists entries;
  create table entries (
          id integer primary key autoincrement,
          title text not null,
          text text not null
   );

  Kaydedip çıkalım. Database olarak sqlite3 kullanacağız. Yukarıda blog bilgilerimizi ( id, başlık, gövde ) tutacak basit bir tablo oluşturmak için kullanacağımız dosyayı yazdık. id bilgisi primary key dir ve otomatik olarak artar. Devam edelim.

  $ vim flaskr.py

  Açtığımız dosyaya şu satırları ekliyoruz:

  # Gerekli modülleri dahil ettik
  import os
  import sqlite3
  from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash

  # app adında küçük bir uygulama oluşturduk.
  app = Flask(__name__)
  app.config.from_object(__name__)

  # Uygulama için gerekli yapılandırma bilgilerini ekledik.
  app.config.update(dict(
          DATABASE='/tmp/flaskr.db',
          DEBUG=True,
          SECRET_KEY=’development key’,
          USERNAME=’admin’,
          PASSWORD=’default’
  ))
  app.config.from_envvar(’FLASKR_SETTINGS’, silent=True)

# Özel bir veritabanına bağlantı yapmak için     def connect_db():
          rv = sqlite3.connect(app.config[’DATABASE’])
          rv.row_factory = sqlite3.Row
          return rv

# Veritabanı bağlantısı için gerekli kısım.
  def get_db():
  if not hasattr(g, ’sqlite_db’):
          g.sqlite_db = connect_db()
   return g.sqlite_db

  @app.teardown_appcontext
  def close_db(error):
  if hasattr(g, ’sqlite_db’):
          g.sqlite_db.close()

  # Veritabanını başlatacak kısım
  def init_db():
          with app.app_context():
                  db = get_db()
                  with app.open_resource(’schema.sql’, mode=’r’) as f:
                          db.cursor().executescript(f.read())
                  db.commit()

  # Yazılmış olan blog yazılarını ve başlıklarını görüntüleyecek kısım.
  @app.route(’/’)
  def show_entries():
          db = get_db()
          cur = db.execute(’select title, text from entries order by id desc’)
          entries = cur.fetchall()
          return render_template(’show_entries.html’, entries=entries)

  # Yeni bir blog girdisinin veritabanına girişini sağlayan kısım.
  @app.route(’/add’, methods=[’POST’])
  def add_entry():
          if not session.get(’logged_in’):
                  abort(401)
          db = get_db()
          db.execute(’insert into entries (title, text) values (?, ?)’, [request.form[’title’], request.form[’text’]])
          db.commit()
          flash(’New entry was successfully posted’)
          return redirect(url_for(’show_entries’))

  # Giriş yapmayı sağlayan kısım
  @app.route(’/login’, methods=[’GET’, ’POST’])
  def login():
          error = None
          if request.method == ’POST’:
                  if request.form[’username’] != app.config[’USERNAME’]:
                          error = ’Invalid username’
                  elif request.form[’password’] != app.config[’PASSWORD’]:
                          error = ’Invalid password’
                  else:
                          session[’logged_in’] = True
                          flash(’You were logged in’)
                          return redirect(url_for(’show_entries’))
          return render_template(’login.html’, error=error)


  # Çıkış yapmayı sağlayan kısım
  @app.route(’/logout’)
  def logout():
          session.pop(’logged_in’, None)
          flash(’You were logged out’)
          return redirect(url_for(’show_entries’))

  # Uygulamayı başlatan kısım
  if __name__ == ’__main__’:
          app.run()

    Bu dosyayı kaydedip çıkıyoruz. Komut satırında veri tabanınındaki tablomuzun oluşması için şu komutu  veriyoruz:

  $ sqlite3 /tmp/flaskr.db < schema.sql

  Veri tabanını başlatmak için python kabuğunda şu komutları veriyoruz:

  $ python
  >>> from flaskr import init_db
  >>> init_db()


  Şimdi gereken şablonları ekleyelim:

  $ mkdir templates
  $ cd templates
  $ vim layout.html

  Açılan dosyaya şu satırları ekleyelim:

  <!doctype html>
 <title>Flaskr</title>
 <link rel=stylesheet type=text/css href="{{ url_for(’static’, filename=’style.css’) }}">
 <div class=page>
   <h1>Flaskr</h1>
     <div class=metanav>
     {% if not session.logged_in %}
       <a href="{{ url_for(’login’) }}">log in</a>
     {% else %}
       <a href="{{ url_for(’logout’) }}">log out</a>
     {% endif %}
     </div>
     {% for message in get_flashed_messages() %}
       <div class=flash>{{ message }}</div>
     {% endfor %}
     {% block body %}{% endblock %}
   </div>

  Kaydedip çıkalım. Blog girdilerini göstermek için bir şablon ekleyelim

  $ vim show_entries.html

  Açılan dosyaya şu satırları ekleyelim:

  {% extends "layout.html" %}
  {% block body %}
    {% if session.logged_in %}
       <form action="{{ url_for(’add_entry’) }}" method=post class=add-entry>
       <dl>
         <dt>Title:
           <dd><input type=text size=30 name=title>
         <dt>Text:
           <dd><textarea name=text rows=5 cols=40></textarea>
           <dd><input type=submit value=Share>
       </dl> 
     </form>
  {% endif %}
  <ul class=entries>
  {% for entry in entries %}
     <li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
  {% else %}
     <li><em>Unbelievable. No entries here so far</em>
  {% endfor %}
   </ul>
{% endblock %}

  Kaydedip çıkalım. Şimdi giriş için bir şablon ekleyelim:

  $ vim login.html

  Açılan dosyaya şunları ekleyelim:

  {% extends "layout.html" %}
  {% block body %}
    <h2>Login</h2>
    {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
     <form action="{{ url_for(’login’) }}" method=post>
       <dl>
         <dt>Username:
           <dd><input type=text name=username>
        <dt>Password:
          <dd><input type=password name=password>
        <dd><input type=submit value=Login>
      </dl>
    </form>
  {% endblock %}

 Kaydedip çıkalım. Şimdi görünümü iyileştirmek için css dosyası ekleyeceğiz. 

 $ cd ..
 $ mkdir static
 $ cd static
 $ vim style.css

 Açılan dosya içine şunları ekleyelim: 

 body            { font-family: sans-serif; background: #eee; }
 a, h1, h2       { color: #377ba8; }
 h1, h2          { font-family: ’Georgia’, serif; margin: 0; }
 h1              { border-bottom: 2px solid #eee; }
 h2              { font-size: 1.2em; }

 .page           { margin: 2em auto; width: 35em; border: 5px solid #ccc; padding: 0.8em;  background: white; }
 .entries        { list-style: none; margin: 0; padding: 0; }
 .entries li     { margin: 0.8em 1.2em; }
 .entries li h2  { margin-left: -1em; }
 .add-entry      { font-size: 0.9em; border-bottom: 1px solid #ccc; }
 .add-entry dl   { font-weight: bold; }
 .metanav        { text-align: right; font-size: 0.8em; padding: 0.3em; margin-bottom: 1em;  background: #fafafa; }
 .flash          { background: #cee5F5; padding: 0.5em; border: 1px solid #aacbe2; }
 .error          { background: #f0d6d6; padding: 0.5em; }


  Dosyayı kaydedip çıkabiliriz. 


  Şimdi flaskr.py dosyasının olduğu dizine geçelim ve uygulamayı çalıştıralım

  $ cd ..
  $ python flaskr.py

  Komut satırında karşımıza çıkan url yi tarayıcıya yazarak uygulamanın nasıl çalıştığını görebiliriz.


  

Flask Hello World

  Merhabalar

  Bu yaz stajımda kullanacağım web uygulama çatısı Flask ile basit bir örneğin nasıl yapıldığından bahsedeceğim.

  Flask'ın kurulumuyla başlayalım:
   
  Python ile geliştirme yapacaksak "virtualenv" yani sanal geliştirme ortamını kurmamız kolaylık sağlayacaktır.

  $ sudo pip install virtualenv
  $ mkdir myproject
  $ cd myproject
  $ virtualenv venv
  $ . venv/bin/activate
  $ pip install Flask 

  Şu anda bulunduğumuz dizin içinde "flask" adında bir dizin oluşmuş olmalı. O dizinin içindeki bin dizininin yolunu PATH 'e eklememiz gerekiyor.

  $ vim ~/.profile
 
  Açılan dosyanın sonuna şu satırı ekliyoruz ( bin kendi dosya sisteminizde neredeyse onun yolunu yazmalısınız ) :

  export PATH=~/myproject/flask/bin:$PATH

  Yaptığımız değişikliği aktif etmek için şu komutu veriyoruz:

  $ source ~/.profile

  Flask projelerinin dosya yapısı şu şekildedir :

             /hello_world
                   /static
                   /templates

  static            => css ve javascript dosyaları bu dizinin altında olur.
  templates     => içinde de şablon dosyalarımızı tutarız.

  İlk uygulama için bu dizinlere şimdilik ihtiyacımız yok. Şimdi ilk uygulamamıza geçebiliriz. Bunu yaparken uygulamalarımız için myproject dizininden farklı bir dizin seçersek karışıklığı önleyebiliriz.

  $ mkdir hello_world
  $ cd hello_world
  $ vim hello.py
  
  Açtığımız dosya içine şu satırları ekliyoruz:
  
  from flask import Flask
 app = Flask(__name__)
  
@app.route('/')
@app.route('/index')
def index():
    return "Hello World!"
app.run(debug = True)

  Dosyayı kaydedip çıkıyoruz. 

    $ python hello.py

  Bu komutu çalıştırdığımızda eğer bir sorun yoksa şu çıktıyı verecektir:
    
    * Running on http://127.0.0.1:5000/
 
  Çıktıdaki url yi browser'ın adres çubuğuna yazdığımızda ekranda Hello World! yazdığını görebiliriz.