theduke hari 1

Apakah ada cara untuk belajar pemrograman selain dengan membuat sebuah
project? oleh karena itu setelah membaca specifikasi wsgi, maka saya
memutuskan untuk membuat sebuah blog engine project dengan menggunakan
python dan wsgi.

blog engine ini akan saya namankan project ‘theduke’, bukan duke
maskot Java, akan tetapi theduke, diilhami oleh nama anak buah Jet
dari film animasi Avatar.

Senjata yang digunakan:

  1. werkzeug

    Kenapa harus werkzeug?, tidak ada alasn khusus, saya hanya
    tertarik dengan namanya saja.Tentu saja, ada calon kuat yang lain
    diantaranya adalah webob, akan tetapi saya melihat werkzeug lebih
    sederhana daripada webob/paste.

  2. sqlalchemy

    Kalo yang ini tidak harus ditanyakan.

  3. jinja

    Tutorial werkzeug banyak menggunakan Jinja, jadi saya pilih Jinja
    saja.

Ada pertanyaan, kenapa tidak menggunakan framework yang sudah jadi
saja, seperti django? hmm, django adalah framework yang bagus, tapi
untuk project ini saya cenderung lebih ke antiframework. werkzueg
sendiri berfungsi seperti glue (lem) yang menghubungkan antara model
dan view. Dan juga sepertinya untuk newbie seperti saya, lebih baik
belajar dari bawah (dalam hal ini lebih ke wsgi).

Untuk project theduke, paling tidak ada beberapa model dasar, yaitu:

  • post
  • author
  • tag
  • comment

dimana hubungan antara model-model tersebut antara lain:

  • one-to-many : author -> post
  • one-to-many : post ->comment
  • many-to-many: post ->tag

berikut ini adalah module database yang menggambarkan table, object,
dan mapper antara table dan object.

#table author
author_table = Table('authors',metadata,
                     Column('id',Integer,primary_key=True),
                     Column('username',String(255),nullable=False,unique=True),
                     Column('password',String(255)),
                     Column('email',String(255),nullable=False,unique=True))

#table post
post_table = Table('posts',metadata,
                   Column('id',Integer,primary_key=True),
                   Column('author_id',Integer,ForeignKey('authors.id')),
                   Column('content',Text),
                   Column('title',String(255)),
                   Column('slugs',String(255),unique=True),
                   Column('excerpt',Text),
                   Column('status',Integer),
                   Column('comment_status',Integer(3)),
                   Column('created',DateTime,default=datetime.datetime.now()),
                   Column('updated',DateTime,default=datetime.datetime.now(),onupdate=datetime.datetime.now()))

#table comment
comment_table = Table('comments',metadata,
                      Column('id',Integer,primary_key=True),
                      Column('author_name',String(255),nullable=False),
                      Column('author_email',String(255),nullable=False),
                      Column('author_url',String(255),nullable=False),
                      Column('author_content',Text),
                      Column('post_id',Integer,ForeignKey('posts.id')))

#table tag
tag_table = Table('tags',metadata,
                  Column('id',Integer,primary_key=True),
                  Column('tag_string',String(255),nullable=False),
                  Column('slugs',String(255),nullable=False))

#table for many to many post and tag
post_tag_table = Table('post_tag',metadata,
                       Column('post_id',Integer,ForeignKey('posts.id')),
                       Column('tag_id',Integer,ForeignKey('tags.id')))

class Author(object):
    pass

class Post(object):
    def __init__(self,title,content,excerpt="",status=0,comment_status=0):
        self.title = title
        self.content = content
        self.excerpt = excerpt
        self.status = status
        self.comment_statut = comment_status
        self.slug_title()

    def slug_title(self):
        self.slugs = self.title.replace(" ","-")


class Comment(object):
    pass

class Tag(object):
    def __init__(self,tag_string):
        self.tag_string = tag_string
        self.create_slugs()

    def create_slugs(self):
        if not self.tag_string:
            raise Exception

        self.slugs = self.tag_string.replace(' ','-')



mapper(Author,author_table,
       properties={'posts':relation( Post, backref='author' )})

#one to many with comments
#many to many with tags
mapper(Post,post_table,
       properties={'comments':relation(Comment, backref='post'),
                   'tags':relation(Tag,secondary=post_tag_table,backref='posts')})

mapper(Comment,comment_table)
mapper(Tag,tag_table)

saya juga membuat sebuah fungsi test

def test(db_uri='sqlite:///test.db'):
    """
    This is just for testing
    """
    engine = create_engine(db_uri)
    metadata.drop_all(bind=engine)
    metadata.create_all(bind=engine)
    Session = sessionmaker(bind=engine)

    #create post
    p = Post("this is a hello world","Hello world")

    t = Tag("tag")
    t1 = Tag("tag2")

    p.tags.append(t)
    p.tags.append(t1)

    session = Session()
    session.save(p)
    session.commit()

    #qtag = session.query(Tag)
    #qtag = session.query(Post)
    return session

dan test langsung dari python console

 c = theduke.database.test()
 d = c.query(theduke.database.Tag)

langkah selanjutnya? Routing

mengenal WSGI

Tentang WSGI

Apa itu WSGI

wsgi::
Web Server Gateway Interface

untuk membuat standard interface antara web aplikasi yang dibuat
dengan python dengan web server.
WSGI mempunyai dua sisi:

  1. sisi server
  2. aplikasi / framework
  3. WSGI pada dasarnya hanya sebuah referensi interface yang harus
    diimplementasi baik oleh server maupun oleh applikasi, sehingga
    sebuah applikasi yang mengimplementasi wsgi dapat di-deploy,
    diserver mana saja asalkan server itu juga mengimplementasi WSGI
    interface.

    Ini dapat dibandingkan dengan dunia java, dimana banyak terdapat web
    framework, akan tetapi web framework itu bisa diapplikasikan di java
    web server mana saja, karena baik web framework maupun java web
    server mengimplentasi JavaEE interface yang salah satunya adalah
    servlet.

    Cara Kerja WSGI

    Server berhubungan dengan applikasi dengan memanggil sebuah callable
    (baik itu fungsi maupun object) yang disediakan oleh
    applikasi. callable itu mempunyai dua buah argumen yaitu environ dan
    start_response. Environ berupa python dictionary sedangkan
    start_response berupa fungsi.

    Sedangkan applikasi berhubungan dengan server, dengan mengirimkan
    header (dapat diartikan sebagai http header), dan memanggil
    start_response dan memberi argumen http response dan http header,
    kemudian mengembalikan list python yang berisi response. Agak
    membingunkan bila cuma membaca spesikasi, akan lebih mudah bila kita
    melihat contohnya

     def application(environ, start_response):
        "Contoh Sederhana dari WSGI Application"
        status = "200 OK"
        headers = [("Content-type","plain/text")]
        start_response(status,headers)
        return ['Hello world !\n']
      
    

    dari contoh diatas, bisa kita lihat bagaimana applikasi berhubungan
    dengan server, dimana applikasi mengirimkan status dan header dengan
    menggunakan fungsi start_response, dan mengembalikan body response
    kepada server.

    Middleware

    Yang dimaksud dengan middleware, adalah sebuah komponen python, yang
    mempunyai dua fungsi sebagai server, sekaligus sebagai
    applikasi. Pada awalnya memang membuat bingung, bagaimana bisa
    sebuah component dapat berfungsi sebagai server sekaligus sebagai
    aplikasi?.
    Jadi bila sebuah komponen berfungsi sebagai middleware, maka dia
    bertindak sebagai penengah/buffer/pembungkus dari applikasi
    lain. Jadi server tidak akan memanggil fungsi dari wsgi dari
    aplikasi,akan tetapi memanggil fungsi wsgi dari komponen middleware,
    yang nantinya akan memanggil fungsi wsgi dari applikasi.
    Middleware itu sendiri bisa merubah keluaran dari applikasi,
    melakukan routing dan berbagai macam hal lainnya.
    Contoh code dari Middleware

    class Upperware:
       def __init__(self, app):
          self.wrapped_app = app
    
       def __call__(self, environ, start_response):
          for data in self.wrapped_app(environ, start_response):
             return data.upper()
    
      
    

    contoh diatas , akan merubah keluaran dari aplikasi yang dibungkus
    middleware, menjadi huruf besar semua.

    contoh penggunaan:

      wrapped_app = Upperware(simple_app)
      serve(wrapped_app)
      
    

    Isi dari Environ

    Environ sendiri adalah sebuah dictionary yang berisi key dan value
    yang berasal dari CGI environment.

    berikut ini beberapa key yang terdapat pada environ:

    REQUEST_METHOD

    HTTP method, dapat berupa post atau get ataupun HTTP method lainya.
    SCRIPT_NAME

    PATH_INFO

    QUERY_STRING

    Query String

    CONTENT_TYPE

    CONTENT_LENGTH

    SERVER_NAME, SERVER_PORT

    SERVER_PROTOCOL

    HTTP_ Variables

    referensi
    - http://python.org/dev/peps/pep-0333/
    - WSGI Gateway or Glue

Emacs,GTD dan OrgMode

Hari ini sebenarnya ingin memperdalam masalah python dan cgi, dengan
mengulik lebih lanjut module cookie. Tapi entah kenapa ketika emacs
dibuka untuk membuat script python, sepertinya hari ini lebih tertarik
untuk mengoprek emacs saja daripada mengoprek python.

Sebenarnya awal dari ini adalah keinginan untuk mengganti todo
list
harian saya dari buku saku ke komputer, dan karena setiap
hari yang paling sering software yang dibuka adalah emacs, maka jadi
penasaran , untuk membuat todo list yang bisa diatur dan dicustomize
pada emacs.

Yang saya cari sebenernya bukan todo list yang sederhana, tetapi
pendekatan todo list dengan get things done (GTD).

Setelah browsing2 dan googling Ada beberapa alternatif:
- Membuat file plain text biasa :P
- menggunakan PlannerMode
- menggunakan orgmode

Akhirnya diputuskan untuk pake orgmode saja, karena lebih sederhana
dibanding memakai planner, akan tetapi jauh lebih powerfull dibanding
plain text biasa.

ini ada beberapa references yang dipakai waktu menginstall dan
mengkustumisasi orgmode
http://members.optusnet.com.au/~charles57/GTD/orgmode.html
http://dto.mamalala.org/notebook/orgtutorial.html
http://www.lifehack.org/articles/lifehack/using-emacs-org-mode-for-gtd.html
http://sachachua.com/wp/2007/12/28/emacs-getting-things-done-with-org-basic/

sekilas python dan cgi

Untuk membuat web applikasi, kita dapat menggunakan bahasa pemrograman apa saja, kita dapat menggunakan bahasa perl, php, java, atau python. Yang akan kita bicarakan kali ini adalah membuat web applikasi dengan menggunakan python.

Untuk membuat web applikasi dengan menggunakan python ada beberapa jalur/pilihan yand diambil:

  • cgi
  • mod-python (bila menggunakan apache)
  • wsgi
  • python application server

pada posting kali ini, yang akan dibahas lebih lanjut adalah cgi, karena cgi adalah metode yang paling tua dan paling sederhana ( meskipun bisa dikatakan pling merepotkan).

CGI ::
cgi merupakan singkatan dari common gateway interface. cgi merupakan protokol untuk menghubungkan antara server dan client. Kita bisa menggunakan bahasa apapun selama bahasa pemrograman itu sudah terdapat di server.

contoh sebuah script cgi dengan menggunakan python


#!/usr/bin/python

print "Content-Type:plain/text\r\n"
print "Hello World"


disave di folder cgi-bin anda (bila menggunakan ubuntu+apache terdapat di folder /usr/lib/cgi-bin/). dan beri mode eksekusi.
mari kita bahas baris perbaris.

baris 1: merupakan perintah shebang pada linux, yang menyatakan program yang digunakan untuk mengeksekusi script.
baris 3: perintah menulis header
baris 4: perintah untuk menulis content.

Form

Untuk menghandle form, yang kita butuhkan hanya class FieldStorage
dari module cgi.

form = cgi.FieldStorage()

misal ada sebuah halaman form:

Name:


maka untuk process script adalah sebagai berikut

import cgi
form = cgi.FieldStorage() # instantiate only once!
nama = form.getfirst('nama', 'empty')

# Avoid script injection escaping the user input
nama = cgi.escape(nama)

print """\
Content-Type: text/html\n

Nama anda adalah "%s"

""" % nama

method getFirst akan mengembalikan nilai pertama dari forms,
bila terdapat lebih dari satu form, maka nilai pengembalian adalah
nilai pertama. Dan sebalikanya bila tidak terdapat form dengan nama
yang dicari, maka nilai dari kembalian adalah None

Bila dalam satu forms, terdapat form dengan nama yang sama (misalnya
check box) maka kita dapat mengetahui nilainya dengan menggunakan
method getList

Cookie

Cookie berperan sangat penting dalam pengembangan aplikasi web, karena
cookie dapat membantu dalam menyimpan State dari web
aplikasi.
Untuk pengolahan cookie, dapat secara manual, dalam arti membaca
header dari HTTP, atau juga kita dapat menggunakan module Cookie, yang
merupakan wrapper dari pembacaan cookie secara manual.
Paling tidak ada 2 hal yang harus dimengerti ketika akan
menggunakan cookie di python-cgi.

Menyimpan/Mengirim Cookie

Mari kita lihat langsung contoh script untuk menyimpan cookie, secara manual..

#!/usr/bin/python

import time

print "Set-Cookie:last-visit="+str(time.time())
print "Content-Type:plain/html \r\n"

#print the content
print ""
print "Hello World"
print ""

dan apabila kita menggunakan module Cookie.

#!/usr/bin/python

import time
import Cookie

cookie = Cookie.SimpleCookie()
cookie['last-visit'] = str(time.time())
print cookie
print "Content-Type:plain/html \r\n"

#print the content
print ""
print "Hello World"
print ""

Gampang dan mudah :).

Membaca Cookie

Berikut ini adalah contoh untuk membaca cookie dengan Module Cookie.

import Cookie
import cgi

cookie_string = cgi.os.environ.get('HTTP_COOKIE')
if not cookie_string:
print "Belum ada Cookie atau Cookie tidak didukung"
else:
cookie = Cookie.SimpleCookie()
cookie.load(cookie_string)
value = cookie['lastvisit'].value

python dan glob

Hari ini saya mencari cara mudah untuk melakukan iterasi terhadap file-file yang ada di folder.

O ya, karena sedang belajar python, maka saya mencari cara untuk hal diatas dengan menggunakan python style

setelah membaca manual, maka kita dapat menggunakan modul os. Yang kita butuhkan terdapat dalam perintah listdir.

import os

listfile = os.listdir(‘.’)

Akan tetapi, bila kita ingin membuat list yang hanya berisi file jpg, paling tidak harus melakukan langkah kedua

import os

listfile = os.listdir(‘.’)
listjpg = [x for x in listfile if x.endswith('jpg')]

Ternyata terdapat cara(module) lain yang dapat melakukan hal diatas dengan cara yang lebih mudah, module tersebut adalah glob.

import glob

glob.glob(‘*.jpg’)

tcl and print

Quick post,

I got a lot of image file that has to be printed, of course I could fire my gimp and print it one by one, but since (again) I am in lazy mood, and beside that I am in linux, so I could use my command line power rigght? rigggght.

so I open my tcl (don’t ask why I choose tcl :P)
and do this

% set filelist [exec ls]
% foreach file $filelist { lpr $file }

sweet, no I just go browsing and wait for my file .

NOTE
only use if you in linux, and already installed cups, and tcl heheh

me and BeanShell

Recently I got an assignment to fool around with a java library, Since I
kind in bad mood, I was thinking a way to fool around with an easy
way, not using code, compile, see because it’s just too much work. So
I remember about java scripting, there are lot of scripting in java
today, here some of it bsh, groovy, jacl, jython, rhino and others.

So I’ve to pick up one from many, I started with bsh, since the
syntax resembling java syntax with some improvement (pre java 5.0). So
I started to download it [ in ubuntu bsh already in synaptix ], and
start to playing around with it.

my first problem is how to add a jar to bsh classpath, luckily in bsh
documentation, there is a command to add jar into classpath,
here’s my snippet

BeanShell 2.0b4 - by Pat Niemeyer (pat@pat.net)
bsh % addClassPath("lib/my.jar");
addClassPath("lib/my.jar");
bsh %

after that, I smoothly played around with the API. so bsh can be a
tool for black-box testing, and I quite satisfied using it. I know
that the other scripting can be use for it, but for now I keep with
bsh for black box testing.

Follow

Get every new post delivered to your Inbox.