16 Kasım 2013 Cumartesi

Python Metot Türleri @classmethod @staticmethod


Python sınıflarında, temel olarak 3 farklı şekilde metot tanımı yapılabilir.
  • Örnek (Instance) metotları
  • Statik (@staticmethod) metotlar
  • Sınıf (@classmethod) metotları
Bunların arasındaki başlıca fark, aldıkları argümanlardır. Örnek metotlarına, ilk argüman olarak, objenin kendisine bir referans gönderilir. Bu argümana, geleneksel olarak self adı verilir. Statik metotlar, kendisini çağıran sınıf veya örnek hakkında herhangi bir bilgiye sahip değildir. Bunlar, işlevini kaybetmeden, sınıf dışında da aynı şekilde tanımlanabilir. Sınıf metotları ise, otomatik olarak, kendisini çağıran sınıfa veya örneğin sınıfına bir referans alır. Bu argümana da geleneksel olarak cls adı verilir.

Örnek (Instance) Metotları

 

Python'da yeni bir sınıf tanımlandığınız, yazdığınız metotlar öntanımlı olarak, örnek (instance) metotlarıdır. Örnek metotları, ilk argüman olarak, kendisini çağıran örneğe bir referans alır. Böylece, geçerli örneğin niteliklerine erişim ve müdahale imkanı bulurlar. Aşağıdaki kodları inceleyelim;

 

class ikisayi(object):

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def toplam(self):
        return self.a + self.b


x = ikisayi(3,5)
print(x.toplam) # 1
print(ikisayi.toplam) # 2
print(x.toplam()) # 3
print(ikisayi.toplam(x)) # 4 
 
Programın çıktısı:
#1: <bound method ikisayi.toplam of <__main__.ikisayi object at 0x021F0390>> #2: <unbound method ikisayi.toplam> #3: 8 #4: 8 Yukarıda, görmeye alışık olduğunuz türden bir sınıf tanımımız var. Bu sınıf, iki tane sayı hakkında veri tutmak için kullanılıyor. Yine, bolca karşınıza çıkacağı gibi __init__ başlangıç metodu var. toplam metodu ise, normal şekilde tanımlanmış, yani bir örnek (instance) metodu. toplam metodumuz, her örnek metodunda olduğu gibi, zorunlu bir ilk argüman alıyor. Bu argümana, çalışma anında oluşturulmuş bir ikisayı objesi geçirilecek. Böylece, toplam metodu, hangi objenin a niteliğiyle b niteliğini toplaması gerektiğini bilebilecek.
Program çıktısına dikkat edersek, x.toplam metodunun bound method olduğunu görüyoruz.Yani, ikisayi.toplam metodu belirtilen adresdeki ikisayi objesine bağlanmış. Yani, x.toplam metodu çağırıldığında, ikisayi.toplam metodu, ilk argüman olarak, o adresdeki objeyi alacak.
Diğer yandan, aynı metoda, sınıf üzerinde eriştiğimizde, bir unbound method buluyoruz.Yani, bu method, herhangi bir örneğe bağlanmamış. Dolayısıyla, otomatik bir ilk argüman almayacak. Eğer ikisayi.toplam() şeklinde çağırırsanız, aşağıdaki hatayı alırsınız:
TypeError: unbound method toplam() must be called with ikisayi instance as first argument
#3 ve #4 numaralı ifadeler aynı çıktıyı veriyor, çünkü, teknik olarak aynı şeyler. Siz, x.toplam() çağırdığınızda, Python bunu kendi içinde ikisayi.toplam(x) şekline dönüştürüyor.

Statik Metotlar

Statik Metotlar, kendisini hangi sınıf veya örneğin çağırdığını bilmez. Sadece kendine verilen argümanları bilir, örnek veya sınıf metotları gibi, gizli bir ilk argüman almazlar. Bu yönden bakıldığında, bu fonksiyonun sınıf içinde yazılmasıyla, sınıf dışında yazılması arasında, hiçbir fark yoktur. Ancak, aynı modül içerisindeki birçok fonksiyonu anlamsal bütünler içinde toplamak gerektiğinde kullanılabilir. Bunları tanımlamak için, metot tanımından önce @staticmethod dekoratörü kullanılır.

Sınıf Metotları

Diğer yandan, sınıf metotları, ilk argüman olarak, kendisini çağıran sınıfa veya kendisini çağıran örneğin sınıfına mecburi/otomatik bir referans alır. Bunu o sınıfın bir örneğini oluşturmak istediğiniz durumlarda (bkz: Factory) kullanabilirsiniz. Kendisini çağıran sınıfa bir referans aldığı için, alt sınıflarda da istenildiği gibi çalışacaktır. Örneğin, diyelim ki, bir telefon numarasını temsil eden bir sınıfınız var:
class TelNo(object):

    def __init__(self, ulkekodu, alankodu, numara):
        self.ulkekodu = ulkekodu
        self.alankodu = alankodu
        self.numara = numara
Burada, bir telefon numarasının, ülke kodu, alan kodu ve numrasını ayrı değişkenlerde tutan bir sınıf tanımladık. Muhtelemen, elimizdeki telefon numaraları, bir dosya veya veritabanında "+90 507 7997272" gibi karakter dizileri içerisinde tutuluyordur. Dolayısıyla, böyle karakter dizilerinden TelNo objesi üreten bir fonksiyona ihtiyacımız olacak.
def str_to_telno(string):
    return TelNo(*string.split(" "))

mytel = str_to_telno("+90 507 7997272")
str_to_telno fonksiyonu, verilen karakter dizisini boşluklarından bölüp, bunlardan yeni bir TelNo objesi oluşturuyor. Telefon numarası tutabilmek güzel ama, bu numarayı arayabilmemiz daha da güzel olurdu. Bunun için, TelNo'nun aranabilen bir alt sınıfını oluşturalım.
class AranabilenTelNo(TelNo):

    def ara(self):
        "bu numaraya VOIP üzerinden bağlantı kur"
        pass # gerçekten bu fonksiyonu kodlamamı beklemiyordunuz umarım :)

def str_to_aranabilentelno(string):
    return AranabilenTelNo(*string.split(" "))
Aynı TelNo'da yaptığımız gibi, bir karakter dizisinden AranabilenTelNo oluşturan bir fonksiyon da tanımladık.
Bu yöntemin şöyle bir sıkıntısı var. Diyelim ki, ileride, mesaj atılabilen telno, mms gönderilebilen tel no vs. gibi bir çok alt sınıf tanımlayacaksınız. Her seferinde tek tek bu dönüşüm işlemini yapmak hem yorucu olacak, hem de kodlar çorba olacak.
Buna alternatif olarak, TelNo objesinde, from_string isminde bir @classmethod tanımladığımızda, ne olduğuna bakalım;
class TelNo(object):
    def __init__(self, ulkekodu, alankodu, numara):
        self.ulkekodu = ulkekodu
        self.alankodu = alankodu
        self.numara = numara

    @classmethod
    def from_string(cls, string):
        return cls(*string.split(" "))

class AranabilenTelNo(TelNo):
    def ara(self):
        pass

mytel = TelNo.from_string("+90 507 7997272")
print(type(mytel)) # 1
myaranabilentel = AranabilenTelNo.from_string("+90 507 7997272")
print(type(myaranabilentel)) # 2
Program Çıktısı:
#1: <class '__main__.TelNo'> #2: <class '__main__.AranabilenTelNo'> Program çıktısından görebileceğiniz gibi, iki sınıfın from_string metotları, doğru sınıfa ait objeler oluşturuyor. Böylece, hem alt sınıf için tekrar ayrı fonksiyon yazmak zorunda kalmadık, hem de, doğru sınıfa ait bir örnek oluşturabildik.
Dikkat ettiyseniz, @classmethod ile tanımladığımız metotları, doğrudan sınıf üzerinden çağırdık. Halbuki, Örnek (Instance) metotlarını, sınıfın bir örneği üzerinden çağırıyorduk. Özetle, sınıfın kendisi ile ilgili işlem yapılacak durumlarda, @classmethod kullanabiliriz.s
 

 

 

 

10 Kasım 2013 Pazar

Tornado websocket client

Tornado'nun sunucu hizmetleri ile ilgili bir sürü örnek var ama istemci olarak hele hele WebSocket için neredeyse hiçbir örnek bulamadım internette, onun için buraya yazalım dursun, bir gün birine lazım olur.

from tornado import websocket, ioloop, gen, escape

class SocketClient():
    def __init__(self):
        self.headers = httputil.HTTPHeaders()
        self.headers['Content-Type'] = 'application/json'
        self.request = httpclient.HTTPRequest(
            url = "wss://some.url",
            validate_cert = False,
            client_key = "client-key.pem",
            client_cert = "client-cert.pem",
            connect_timeout = 60,
            request_timeout = 60)


    def connect(self, connCallback, msgCallback):
        self.request.headers = self.headers
        self.__msgcallback = msgCallback
        self.__conncallback = connCallback
        wssConn = websocket.WebSocketClientConnection(ioloop.IOLoop.current(), self.request)
        wssConn.connect_future.add_done_callback(self.__on_connResult)




    def __on_connResult(self, conn):
        if conn.exception() == None:
            self.__wssConn = conn.result()
            self.__conncallback(True)
            self.__read()
        else:
            print(conn.exception().args)
            self.__conncallback(False)




    def send(self, data):
        self.__wssConn.write_message(escape.utf8(json.dumps(data)))




    @gen.coroutine
    def __read(self):
        while True:
            msg = yield self.__wssConn.read_message()
            if msg is None:
                self.__conncallback(False)
                break
            self.__msgcallback(msg)

Python ile socket programlamaya giriş.

Merhabalar,
Bu yazıda, Python programlama diliyle soketlerin kullanılışı konusuna kısaca giriş yapmaya çalışacağım. Okuyucuda soketler hakkında temel bilgilerin olduğunu varsayıyorum. Bunların ne olduğu veya ne için kullanıldığı konusunda hiçbir bilgisi olmayanlar için şöyle özetleyebiliriz; soketler iletişim kanallarıdır. Bunlar aynı bilgisayarda iki işlem arası iletişim sağlayabilse de (örn: unix soketleri) bunları en çok ağ üzerinde iletişim için kullanırız. İnternetten bilgisayarınıza gelip giden tüm veriler için, mutlaka birer soket kullanılır.
Anlatıma geçmeden önce şunu da söylemek istiyorum ki, Python'daki socket modülünü lazım olmadıkça kullanmayınız. Demek istediğim şu ki, bir internet sayfası indirmek için socket açmak, HTTP başlıklarını göndermek, gerekirse yönlendirilen sayfaya yeniden soket açmak gibi bir uğraşa girmeyin. Python bu tip yaygın kullanımlar için zaten daha üst seviye modüllere sahip bir dil. Amerika'yı yeniden keşfetmeye gerek yok.
Öyleyse, Python'daki socket modülünü alternatif bulamadığımız durumlarda kullanalım. Ağ bakımı/programcılığı konusunda bu modülün kullanım alanı kendisini belli edecektir.
Bir örnekle başlayalım;
s = socket.socket(
  socket.AF_INET, socket.SOCK_STREAM)

s.connect(("www.google.com.tr", 80))
Bu örnekte bir client (ingilizcede müşteri demek) soket oluşturduk. Bunun anlamı, bu soket kendisi veri sunmayacak, bir sunucuya bağlanacak demek. Sunucu programlara ileriki yazılarda göz atmaya çalışacağım.
Soket oluşturma fonksiyonuna ilk verdiğimiz argüman, bu soketin adresleme şeklini gösteriyor diyebiliriz. Bunun socket.AF_INET olması, bunun bildiğimiz IP adresi soketi olduğunu gösteriyor. Bunun yerine, socket.AF_INET6 ile IPv6 kullanabiliriz. Bir de socket.AF_UNIX var ki, bu UNIX soketleri için kullanılıyor. Dolayısıyla her sistemde bu sabit tanımlı olmayabilir.
İkinci argüman ise bu soketin iletişim tipini gösteriyor. socket.SOCK_STREAM, en yaygın kullanılan TCP iletişim tipidir. Bundan sonra en yaygın kullanılan iletişim tipi UDP için socket.SOCK_DGRAM sabiti kullanılır.
Daha sonra, elimizdeki s isimli soket objesinin connect isimli metoduyla, soketimizi internetteki bir diğer sokete (yani sunucuya) bağlayabiliriz. Bu metot adres türüne göre farklı argümanlar alabilir. socket.AF_INET için, adres ve porttan oluşan bir tuple veri tipi alır.
Eğer internetle veya işletim sistemiyle ilgili bir hata oluşmadı ise, şu andan sonra soketimiz yazmak ve okumak için hazır. Bu işlemler için sırasıyla send ve recv metotları kullanılır. Aynı örnekten devam ederek, şunu deneyebiliriz;
s.send("GET / HTTP/1.1\r\nHost: www.google.com.tr\r\nConnection: Close\r\n")
while True:
    msg = s.recv(512) # 512 byte veri okumaya çalış
    if not msg: # Eğer boş döndüyse,
        break
    print msg
Not: Kodlar içerisindeki adres html tagları içinde görünüyorsa, onları kaldırın. Galiba Tumblr otomatik olarak onu linke çevirmeye çalışıyor :/
Burada, muhtemelen yapılabilecek en kısa HTTP isteğini gerçekleştirdik. Daha sonra da, 512 byte'lar halinde okuyabildiğimiz kadar veri okuduk. İnternetten gelecek verinin tümünün ne kadar olduğunu bilmediğimiz için, boş veri okuyana kadar okumaya devam etmemiz gerekiyor. Bir yandan okudukça, bir yandan da ekrana yazmaya devam ettik.
Ekleme: Connection: Close header'ını eklemek önemli. Bu header olmazsa, server yeni bir istek almak için bağlantıyı açık tutabilir. Bu durumda, program bağlantının kapanacağını varsaydığından, bağlantının iki ucu da diğerinden veri beklerken program donabilir. (bkz: HTTP persistent connection)
Artık s isimli soketimizle işimiz bitti. HTTP protokolünde, bir kez veri okuduktan sonra bağlantı kapanır. Yeni bir sayfa okumak istersek, sıfırdan bir soket bağlantısı gerçekleştirmemiz gerekir.
Bu yazıda konuya genel bir giriş yaptım. Bir sonraki yazıda sunucu programlarda soketlerin nasıl kullanılacağına değinmeyi planlıyorum.

Python Modüllerinde __name__ Özelliğinin Kullanımı

Modüller yenilir mi, içilir mi?

Öncelikle python’da modüllerden ufak bi’ bahsedeyim. Bildiğiniz gibi bir betik içersinde kodlarımızı tekrar tekrar yazmamak için bir kez fonksiyon tanımlamamız yeterli. O fonksiyonu kullanarak kodları tekrar kullanabiliyoruz. Peki ya aynı fonksiyona başka bir Python programında da ihtiyacımız olursa ne yapacağız? Cevap tabii ki modül kullanmak.
Python’da modül yazmak için birçok metod var ama bunlardan en basit ve en yaygın olanı fonksiyonlar ve değişkenler için .py uzantılı dosyaları kullanmak. Yani evet, şimdiye kadar yazdığınız her python betiği aynı zamanda birer modül. Diğer bir modül oluşturma yöntemi de C veya C++ programlama dilleri ile yazmaktır.
Yani sonuç olarak python’da modül dediğimiz şey aslında bizim yazdığımız betiklerdir. Yani yazdığımız her python betiği bir modül olarak başka bir betikte içe aktarılabilir(import). Modüller için ayrıca buraya bakabilirsiniz.

Bir modül’ün ismi

Yavaş yavaş asıl değinmek istediğim konuya geleyim. Python’da her modülün bir ismi vardır. Python yorumlayıcısı bir modülü yorumlarken o modüldeki tüm kodları çalıştırmadan önce bazı değişkenler tanımlar. Bunlardan birisi __name__ değişkenidir. Bu değişken, o modül’ün çalıştırılma şekline göre başka değerler alır.
Eğer python yorumlayıcısı bizim yazdığımız modülü ana program olarak çalıştırıyorsa __name__ değişkeni '__main__' değerini alır. Ancak yazmış olduğumuz modül başka bir modül içinden çağırılıyorsa bu sefer __name__ değişkeni kendi modül’ünün adını alır.
Anlaşılması için bunları bir örnekle açıklayayım;
Örneğin ornek_modul.py isminde bir dosyaya kaydedeceğimiz şöyle bir betik yazalım:
__name__ özelliğinin kullanımı
1
2
3
4
if __name__ == '__main__':
    print('Kendi dosyam tarafından çalıştırıldım.')
else:
    print('Başka bir modül tarafından içe aktarılarak çalıştırıldım.')
Şimdi bu betikle ilgili çıktılara bakalım:
çıktı testleri
1
2
3
4
5
6
$ python3 ornek_modul.py
Kendi dosyam tarafından çalıştırıldım.
$ python3
>>> import ornek_modul
Başka bir modül tarafından içe aktarılarak çalıştırıldım.
>>>
Görüldüğü gibi ornek_modul.py doyasını kendi başına çalıştırısak __name__ değişkeni '__main__' değerini alıyor. Fakat python’un etkileşimli kabuğuna girip ornek_modul modülünü içeri aktarırsak 1. koddaki else bloğuna düşeriz çünkü __name__ değişkeni bu defa modülün ismi olan ornek_modul değerini almış olur.

7 Kasım 2013 Perşembe

django web framework kullanmak için rasyonel nedenler .


Merhaba arkadaşlar ben yasin aktimur, ortalama 6 senedir internet üzerinde farklı projeler geliştiriyorum ve gelirimin tamamını  bu projelerindeki ürünleri satarak elde ediyorum.
ilk projelerimi herkes gibi php ile yazıp shared hosting üzerinde paylaşıyordum.
Geliştirdiğim projelerin kullanıcı sayısı olması gerektiğinden çok daha fazla sayılara eriştiriğinde profesyonel bir tercih yapmam gerekti ve şimdi o tercihi yaparken neden django’yu seçtiğimi sizlerle paylaşacağım.
Php ile geliştirilen büyük web siteleri : Wikipedia ve facebook
Wikipedia : 2001 senesinde yazılmış bir internet projesi ve şu anda var olan teknolojilerin hiç birisini kullanmıyor o yüzden 2013 yılında php için  referans gösterilmesi aslında gereksiz.
Facebook : 2004 senesinde kurulduğunda markın farklı bir seçeneği yoktu fakat sonradan friendfeed’e 15 milyon $ nakit ve 32.5  milyon dolar facebook hissesini babasının hayrına vermedi bu kadar para bayılmasının nedeni aslında Python ile yazılmış alt yapısını facebook’a adapte etmekti ve ettide zaten o alt yapıyıda açık kaynak olarak paylaştı. Bu arada yazılımın ismi : tornado web server . Django gibi geniş çaplı değil sadece c10k problemine çözüm getiriyor realtime sistemler için ayrıca django ile adaptasyon sağlayabiliyor yani tek başına tornado bi işe yaramıyor denebilir.
Ruby ile geliştirilen servisler : Twitter , Hulu
Ruby tercih etmeme nedenimde tornadonun python  ile yazılmış olup django ile senkrinizasyonunun yapılabilmesi realtime bir sistem kuracaksanız node.js şart lakin twitter.com ‘un mesajlaşma sistemindeki rezaleti ruby’deyki realtime eksikliğini açıkça gözler önünede seriyor.

4 Kasım 2013 Pazartesi

Paypal ipn with django

Is this your first time integrating Paypal with Django? Can't get the signals to work? Don't know how to test django-paypal on your local machine? Hopefully, this step-by-step blog post will address all the above mentioned problems and more. This tutorial will cover only Paypal Standard IPN although most of the initial steps are applicable for the other payments methods as well.

1. Install django-paypal

There are a couple of version floating around namely: 
Cramer's is a fork from Boxall's version so it's more update. For this tutorial, we will be using Boxall because we found Boxall's first.
  1. git clone git://github.com/johnboxall/django-paypal.git paypal

2. Create a PayPal developer account

  1. Goto https://developer.paypal.com and sign up.
  2. Once you're in, create a preconfigured account
  3. Do this twice, one for account type Buyer and one for account type Seller
  4. Your dashboard should then look like this:

3. Modify settings.py file

  1. For the PAYPAL_RECEIVER_EMAIL, set this to the business account email you created in step 2. In this example, it is naiyun_1311845021_biz@od-eon.com
  2. After you have entered this, run syncdb to create the paypal tables
  1. # settings.py
  2. ...
  3. INSTALLED_APPS = (... 'paypal.standard.ipn', ...)
  4. ...
  5. PAYPAL_RECEIVER_EMAIL = "naiyun_1311845021_biz@od-eon.com" #change this to yours

4. Create a url

# urls.py

  1. from django.conf.urls.defaults import patterns, include, url
  2. urlpatterns = patterns('',
  3. # Examples:
  4. url(r'^$', 'cat.homepage.views.home', name='home'),
  5. url(r'^paypal/$', 'cat.homepage.views.paypal', name='paypal'),
  6. url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
  7. url(r'^admin/', include(admin.site.urls)),
  8. )
  9. urlpatterns += patterns('',
  10. (r'^something/hard/to/guess/', include('paypal.standard.ipn.urls')),
  11. )
  1. Replace cat.homepage with your project.appname

5. Create a view and template

  1. # views.py
  2. ...
  3. from paypal.standard.forms import PayPalPaymentsForm
  4. from django.conf import settings
  5. from django.core.urlresolvers import reverse
  6. def paypal(request):
  7. # What you want the button to do.
  8. paypal_dict = {
  9. "business": settings.PAYPAL_RECEIVER_EMAIL,
  10. "amount": "1.00",
  11. "item_name": "name of the item",
  12. "invoice": "unique-invoice-id",
  13. "notify_url": "%s%s" % (settings.SITE_NAME, reverse('paypal-ipn')),
  14. "return_url": "http://www.example.com/your-return-location/"
  15. "cancel_return": "http://www.example.com/your-cancel-location/",
  16. }
  17. # Create the instance.
  18. form = PayPalPaymentsForm(initial=paypal_dict)
  19. context = {"form": form.sandbox()}
  20. return render_to_response("paypal.html", context)
  21. # paypal.html
  22. {{ form }}
  1. Don't worry about what to put for settings.SITE_NAME first, we'll get to that in a bit
  2. The notify_url is the url that PayPal will try to send a POST request
  3. return_url is the page that Paypal redirects you to when the transaction is complete
  4. The form key in context renders a PayPal button. Right now we're using form.sandbox() to initiate the test process. Change this to form.render() to send the user to the real PayPal site
  5. You can add a "custom" key and value to the paypal_dict if you want to add a custom field later on
  6. If you're doing this test multiple times, you might run into an error message given by Paypal that says something like: This invoice has already been paid. For more information, please contact the merchant. To get around this, just change the invoice value everytime you try to make a purchase.

6. Now we fix the SITE_NAME

Sign up for an account at www.dyndns.com
  1. Add a new hostname. For service type, choose Host with IP address. Next, click on the link to populate the IP Address
  2. You should have something that looks like this:
  3. Add the Hostname to your settings.py file as SITE_NAME like so
  1. # settings.py
  2. ...
  3. SITE_NAME = 'http://nai.dyndns-free.com'
  4. ...

7. Run Django development server on your local IP

  1. For this to work, you need to configure your router to open port 80. The normal process is roughly like this:
    1. Goto your router IP e.g. 192.168.1.1
    2. Look for firewall or port forwarding
    3. Create an exception called 'django' or whatever with port 80 open
    4. Add this exception to the list of allowed applications that is tied to your computer
    5. Save
  2. Now, run Django's development server using sudo /etc/init.d/apache2 stop; sudo ./manage.py runserver 192.168.2.102:80
  3. Change 192.168.2.102:80 to your own IP address which you can locate by running ifconfig in bash. Retain port 80
  4. If all goes well, you should be able to open up in your browser the hostname you created at dyndns. In my case, nai.dyndns-free.com/paypal looks like this:

8. What goes on under the hood?

When someone uses this button to buy something PayPal makes a HTTP POST to your "notify_url" which comes as part of the Paypal package. PayPal calls this Instant Payment Notification (IPN). The view paypal.standard.ipn.views.ipn handles IPN processing. We have already set the notify_url in step 4 as: urlpatterns += patterns('',(r'^something/hard/to/guess/', include('paypal.standard.ipn.urls')),)

When the notify_url is called, the ipn view is executed as shown below. You will need to include @csrf_exempt in the view as well

  1. @require_POST
  2. @csrf_exempt
  3. def ipn(request, item_check_callable=None):
  4. """
  5. PayPal IPN endpoint (notify_url).
  6. Used by both PayPal Payments Pro and Payments Standard to confirm transactions.
  7. http://tinyurl.com/d9vu9d
  8. PayPal IPN Simulator:
  9. https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session
  10. """
  11. flag = None
  12. ipn_obj = None
  13. form = PayPalIPNForm(request.POST)
  14. if form.is_valid():
  15. try:
  16. ipn_obj = form.save(commit=False)
  17. except Exception, e:
  18. flag = "Exception while processing. (%s)" % e
  19. else:
  20. flag = "Invalid form. (%s)" % form.errors
  21. if ipn_obj is None:
  22. ipn_obj = PayPalIPN()
  23. ipn_obj.initialize(request)
  24. if flag is not None:
  25. ipn_obj.set_flag(flag)
  26. else:
  27. # Secrets should only be used over SSL.
  28. if request.is_secure() and 'secret' in request.GET:
  29. ipn_obj.verify_secret(form, request.GET['secret'])
  30. else:
  31. try:
  32. ipn_obj.verify(item_check_callable)
  33. except Exception, e:
  34. flag = "Exception while processing. (%s)" % e
  35. ipn_obj.save()
  36. return HttpResponse("OKAY")

Just to elaborate a bit on the view, this line here ipn_obj.verify(item_check_callable) is the part that will invoke the sending of the signals. The verify() method can be found in paypal/models/standard/models.py which in turn calls the send_signals() method which can be found in paypal/models/standard/ipn/models.py

9. Final Stretch

So now we need to set up something to receive these signals. This can live anywhere in the project. The examples use models, so lets go with that.

  1. # models.py
  2. ...
  3. from paypal.standard.ipn.signals import payment_was_successful
  4. def show_me_the_money(sender, **kwargs):
  5. ipn_obj = sender
  6. # Undertake some action depending upon `ipn_obj`.
  7. if ipn_obj.custom == "Upgrade all users!":
  8. Users.objects.update(paid=True)
  9. print __file__,1, 'This works'
  10. payment_was_successful.connect(show_me_the_money)
  1. If everything works ok when we click the buy now button, console should print the line 'This works'
  2. So, go back to your domain/paypal page. Click on the buy button link, it should re-direct you to the Paypal sandbox page. Log in using the personal account you created in step 2. Mine is naiyun_1311850509_per@od-eon.com
  3. Go through the buying process and if everything works, you should see something like this in your console
  1. [05/Aug/2011 03:06:50] "GET /paypal/ HTTP/1.1" 200 1075
  2. /home/nai/GitProjects/cat/homepage/models.pyc 1 This works
  3. [05/Aug/2011 03:08:02] "POST /something/hard/to/guess/ HTTP/1.0" 200 4

Hope this tutorial has been helpful. If you have any questions, do leave them in the comments and I 'll do my best to answer them. 

UPDATE

Just in case anyone is running into DB related problems, django-paypal uses South to handle it's model creation. So running ./manage.py syncdb will *not* create the Paypal related tables. 
 

2 Kasım 2013 Cumartesi

Django şablon örnekleri..

Projemize template ve render to response ekliyoruz

Views.py
from django import template
from django.shortcuts import render_to_response


def fonksiyon(request):
    return render_to_response('htmldosyasi.html', locas())

Şeklinde çekilir.

Django örnek view dosyası oluşturma.

views.py

#-*- coding: utf-8 -*-
from django.http import *

def merhaba_dunya(request):
    return HttpResponse(u'Merhaba Dünya')


url.py
ikinci satıra ekleyin
import views

urlpatternsin içine ekleyin

url(r'^merhaba/', views.merhaba_dunya)




/////

import random

def rastgele_sayi(request):
    return HttpResponse('Rastgele sayi : , %f'% random.random())


url.py


url(r'^rastgele/', views.rastgele_sayilar),

vsftpd FTP server nedir nasıl kurulur ?

vsftpd very secury ftp server bilmem ne anlamına geliyor ve mesela filezilla programı ile vps serverinıza yada linux herhangi bir serverınıza bağlanacaksınız normalde bağlanamıyorsunuz uzaktan bu programı kurmanız gerekiyor yada cyberduck tarzı programlar..

vsftpd kurlumu

Redhat/fedora/centos dağatımları için
yum install vsftpd
Debian/ubuntu dağatımları için
apt-get install vsftpd
komutlarını kullanarak, komut satırından vsftpd programını rahatça indirebilir ve sisteminize kurabilirsiniz.
Bu işlemleri yapıp programı kurduktan sonra ilk yapmanız gereken vsftpd’ nin configuration yani yapılandırma dosyasını ayarlamaktır.


Çoğu dağatımda bu dosyaya
/etc/vsftpd/ 

Bu dosyaya şu gisti yapıştırın :  vspd raw 



Fark ettiyseniz userlist_deny=NO şeklinde yeni bir ayar girdim. vsftpd klasöründe userlist adında bir dosya daha bulunmaktadır.
Bu dosya içinde ise kullanıcı isimleri bulunmaktadır. Eğer bu dosya içindeki kullanıcı isimlerinin FTP sunucusunu kullanmalarına izin vermek istiyorsanız o zaman userlist_deny=NO şeklinde ayarı vsftpd yapılandırma dosyasına girmelisiniz, eğer bu listedeki kullanıcıların FTP sunucusunu kullanmalarını engellemek istiyorsanız userlist_deny=YES şeklinde ayarlamalısınız. Bu nedenle vsftpd sunucusunu başlatmadan önce bu dosyaya gözatmanızda yarar vardır.
Tüm bu uygulamaları yerine getirdikten sonra ise, artık vsftpd sunucusunu çalıştırabiliriz ve userlist dosyasını ayarladığımız için zaten sistemde kayıtlı bulunan kullanıcıların kullancı adları ve şifrelerini kullanarak sisteme girebiliriz. Bunun için aşağıdaki komutları girmeniz yeterli olacaktır.
/etc/init.d/vsftpd start –> Sunucuyu başlatır
/etc/init.d/vsftpd stop –> Sunucuyu durdurur
/etc/init.d/vsftpd restart –> Sunucuyu yeniden başlatır
Evet artık sunucunuzda çalışan bir FTP server sahibisiniz.

1 Kasım 2013 Cuma

Linux ana dizindeki bin boot dev etc lib media mnt opt sbin srv tmp usr var nedir ne işe yararlar ?

Microsoft Windows gibi bir başka işletim sisteminden, Linux'a geçen son kullanıcıların en büyük sıkıntılarından biri, dosya sistemleri arasındaki farklardır. Windows konusunda biraz tecrübeli kime sorsanız, Program Files, Windows, System32, Documents and Settings klasörleri hakkında bilgi verebilir. Ancak Unix dünyası farklıdır ve geçiş yapan kullanıcılar, hangi klasörün ne işe yaradığını, hangisinin neyle alakalı olduğunu ilk bakışta çözemez. İşin kötü tarafı, farklı dağıtımlar için, dosya sistem hiyerarşisi değişebilir. Bu yazımızda, Linux Dokümantasyon Projesi (The Linux Documentation Project) tarafından yayımlanmış Linux Dosya Sistemi Hiyerarşisini baz alarak, sizlere Linux dosya sistemi hakkında bilgi vereceğiz. Eğer daha çok bilgi almak isterseniz The Linux Documentation Project web sitesini ziyaret etmenizi tavsiye ederim.

 

Dosya Sistemi Nedir?

Dosya sistemi, işletim sisteminin bir disk veya bölüm (partition) üzerindeki dosyaları takip edebilmesi için oluşturulmuş yöntem ve veri yapıları bütünüdür. Dosya sistemi farklı anlamlar için de kullanılıyor. Örneğin iki diski olan bir kullanıcının "İki dosya sistemim var." dediğini duymuşsunuzdur. Buna şimdilik girmeyelim. Bizi ilgilendiren Linux'taki dosya yapısı.
Linux, bir Unix klonudur. Bu yüzden "Tekil Hiyerarşik Klasör Yapısı"nı benimsemiştir. Her şey / (slash) simgesiyle ifade edilen root klasöründen başlar, aşağıya doğru iner. Windows'taki gibi C: D: şeklinde sözde sürücüler (drivers) bulunmaz. Windows ortamında, dosyalarınızı C sürücüsü, D veya E sürücüsü gibi her yere koyabilirsiniz. Bu tarz dosya sistemlerine, "Hiyerarşik Yapı"lı denmektedir.
Linux, / (root) klasöründen başlayarak, boot işlemindeki önem sırasına göre klasörleri dizer. Windows'taki gibi \ (ters slash) işareti değil de / (slash) işareti kullanılmasının nedenini merak edebilirsiniz. Bu Linux'un Unix geleneğini takip etmesindendir. Ayrıca bu geleneğe uygun olarak küçük büyük harf duyarlılığı önemli bir konudur. Örneğin; Windows'ta KLASOR_ADI ve klasor_adi aynı şeydir; fark etmez. Ama Linux'ta iki ayrı klasörden bahsediyor oluruz.
Windows'ta bir program yüklediğinizde, programa ait dosyaların büyük çoğunluğu kendi klasörüne yüklenir. Örneğin Matlab'i, C:\Program Files\Matlab adresine kurduğunuzda, ona ait yardım dosyaları, bu klasör altındadır. Fakat Linux farklı çalışır; program dokümanlarını /usr/share/doc/program_adi/ altına koyarken, man(ual) dosyaları, /usr/share/man/man[1-9] altına koyar. Eğer varsa info dosyaları da, /usr/share/info altına atılır. Kısacası, sistem hiyerarşisine gömülen bir yapı söz konusudur. Yüklenen herhangi bir program, işletim sisteminin muhtelif yerlerine yerleşmektedir.
Linux'un popülerleşmeye başladığı 90'ların ortalarında, dağıtım geliştiriciler, dosyaları yerleştirmek için kendilerine en uygun şekilde çalıştılar; belirli bir standart yoktu. Bu birçok soruna neden oldu. Bu anarşiyi durdurmak için daha sonraları Linux Dosya Sistem Hiyerarşisi (kısaca FSSTND) belirlendi. Bizim anlatacağımız yapı da bu standart dahilinde.
Linux ve dosya sistemiyle ilgili söylenecek çok şey var; ama özet geçip son kullanıcının ihtiyacına cevap vermek daha doğru olur: "Linux'ta hangi klasör ne işe yarar?"
/ (root) : Yukarda belirttiğimiz gibi, / (root) işletim sisteminin başlangıç noktasıdır. Bütün diğer klasörler, dosyalar, root'un 'çocuklarıdır'. Bilgisayar başlarken, ilk önce buraya bakılır ve bulunmazsa sistem başlamaz. / (root) ve /root (root kullanıcısına ait klasör) birbirinden ayrıdır. İleriki bölümde farkını açıklayacağız.

FSSTND'a Göre root Altındaki Temel Klasörler

/bin: Olması şart komut dosyalarını içerir.
/boot: Başlangıç için gerekli dosyaları bulundurur.
/dev: Donanım dosyaları vardır.
/etc: Sistem ayarlarını barındırır.
/lib: Kütüphane dosyaları ve çekirdek modülleri bulunur.
/media: Kaldırılabilir aygıtların (CD-ROM, flash bellek vs...) sisteme eklendiği klasördür.
/mnt: Bir dosya sistemini geçici olarak eklemek için kullanılır.
/opt: Ekstra programların kurulması içindir.
/sbin: Sistemi yöneticisiyle ilgili çalıştırabilir dosyaları tutar.
/srv: Sistemin sunduğu hizmetlerle alakalıdır.
/tmp: Geçici dosyaları tutmak içindir.
/usr: İkincil bir hiyerarşi.
/var: Değişken verileri saklar.
Günümüzde Linux dağıtımlarının büyük çoğunluğu, zaman zaman FSSTND tarafından belirlenmiş klasörlerin dışına çıkabiliyor. Bu tanıma bazen bir iki klasör eklendiğini ya da nadiren bu yapıdan bir klasörün çıkarıldığını görüyoruz. Biz gerek güncel dağıtımları, gerekse FSSTND'yi baz alarak incelememizi yapacağız. Ancak yazımızda FSSTND tarafından belirlenen bütün klasörler olmayacak. Linuxdosya sistemi oldukça derin bir konu ve her şeyi anlatmaya kalkarsak, ayrı bir kitapçık yayımlamamız gerekir. Bunun yerine, son kullanıcının daha çok ilgisini çekecek ve genellikle haşır neşir olabileceği klasörleri ele alacağız.

/bin

İşletim sisteminizi kullanmak için gereken birçok yararlı komut /bin klasörü altındadır. cat, mkdir, cp, ls, mv, rm vb. temel komutların hepsini burada bulabilirsiniz. Sistem boot ettiğinde, ilk olarak /bin klasörü çalışır hâle getirilir. Network bağlantınız olmasa ya da önemli klasörlere bir nedenden dolayı erişemeseniz bile, /bin klasöründeki komutlar ne olursa olsun çalışır. Bir sorun çıktığında, /bin klasörü altındaki komutları kullanarak sistemi onarırız.

/boot

Boot, işletim sisteminin yüklenme evresidir. /boot klasörü, boot işlemi için gereken her şeyi içerir. Bilgisayarın başlangıç (boot) aşamasında gerekmeyen ayar ve yapılandırma dosyaları burada bulunmaz; başka klasörlerden gerektiği zamanlarda yüklenir.

/dev

Linux'ta her şey bir dosyadır; donanım aygıtları da öyle. USB girişleri, seri ve paralel portlar, diskleriniz, CD-ROM'larınız vb... Bütün aygıtlar /dev klasörü altında tutulan dosyalardan ibarettir. Örneğin /dev altında bulunan hda1 dosyası, sabit diskinizi temsil eder. Ya da /dev/dsp, ses aygıtınızdır. Bunları programlar vasıtasıyla kullanırız; ancak direkt müdahale etmek mümkündür. Mesela "cat /boot/vmlinuz > /dev/dsp" yazarak Kernel'in sesini duyabilirsiniz.

Bazı Önemli Aygıt Dosyaları

/dev/ttyS0
Fare, modem gibi aygıtların bağlandığı seri port. (COM 1)
/dev/psaux
PS/2 girişi; fare ve klavyeler içindir.
/dev/lp0
Paralel port (LPT 1); yazıcı, tarayıcı vs...
/dev/dsp
Birincil ses aygıtı
/dev/usb
USB aygıtları 
/dev/sda
SCSI aygıtlar, Flash Bellekler, harici CD-ROM'lar vs...
/dev/scd
SCSI CD-ROM'lar
/dev/js0
Joystick (Microsoft Türkçesiyle Eğlence Çubuğu)

/etc

İşletim sistemini bir vücuda benzetirsek, /etc klasörünü sinir sisteminin merkezi olarak görebiliriz. Sisteme dair bütün yapılandırma, bu klasör veya bu klasörün alt klasörlerinde bulunur. Yapılandırma dosyası, bir programın işlemlerini kontrol etmek için kullanılan lokal bir dosyadır; durağandır ve çalıştırılmak için değildir.
/etc klasörü içerisinde bulunan bütün klasör ve yapılandırma dosyalarını tek tek incelememiz mümkün değil. Ancak son kullanıcının işine yarayacak bir ipucu verebiliriz.
Sürekli DNS problemleri yaşayanlar, /etc/resolv.conf dosyasını root olarak açıp yeni DNS adresleri ekleyebilir. Siz de bu sorunlardan muzdaripseniz, root olarak bu dosyayı açıp aşağıdaki satırları dosyanın en başına ekleyin:
nameserver 208.67.222.222
nameserver 208.67.220.220
Verilen adresler OpenDNS adında bir firmaya ait. Telekom'un adresleri yerine bunları kullanırsanız; adres çözümleme problemleriniz geride kalacaktır. Üstelik erişimi engellenen sitelere de girebilirsiniz.

/home

Zamanında home klasörüyle ilgili hoş bir tanım duymuştum; /home klasörünü kullanıcıların kalesi olarak açıklıyordu. Bu gayet yerinde bir açıklama. /home klasörü içerisinde her kullanıcının kendi adında bir alt klasörü bulunur. Örneğin kullanıcı adınız "ali" ise, /home/ali size aittir ve altında istediğiniz her şeyi yapabilirsiniz; ama yapabilecekleriniz bu klasörle sınırlıdır. /home klasörünü, Windows'taki Documents and Settings'e benzetebiliriz. Ama daha güvenli bir yapıdır. Çünkü Linux'ta bir başkasının ev klasörüne müdahale edemezken, Windows'ta çok zorlanmadan istediğinizi yapabilirsiniz.

/initrd

initrd, "initial ramdisk" kısaltmasıdır. Aşağı yukarı anlamı "Başlangıç Bellek Diski" oluyor. Boot aşamasında ilk önce çekirdek (kernel) yüklenir. Bundan sonra bilgisayarınızın belleğinde bir Bellek Diski oluşturulur. Oluşturulan Bellek Disk üzerinde / (root) yansısı açılır ve kök dizin olarak monte edilir. /initrd bu işlemlerin yapılması ve Linux'un yüklenmesi için gereklidir.

/lib

Çekirdek modülleri ve paylaşılan kütüphane dosyaları bu klasörde bulunur. Var olan çekirdek modüllerini /lib/modules/[versiyon_numarasi] içerisinde bulabilirsiniz. Bahsedilen kütüphane dosyalarıysa, sistemi başlatmak ve /bin ile /sbin içerisindeki komutları çalıştırmak için gereklidir. Paylaşılan kütüphane dosyalarını, Windows'ta DLL (Dynamically Linked Library) ile eş tutabiliriz. Linux'ta kütüphane dosyalarının sonu ".so" ile biter.

/lost+found

İngilizce bir terim olan Lost and Found, "kayıp eşya bürosu" demektir. /lost+found klasörünün yaptığı işi düşününce, bundan uygun bir isim herhâlde olamazdı.
Bazen sistemimizde bir problem olur; yanlış kapatırız, elektrik gider, durup dururken bilgisayar yeniden başlar vs... Bu gibi durumlarda Linux'ta fsck (File System Check) komutu devreye sokulur. fsck, Windows'taki Scandisk programına benzetilebilir. Düzeltilemeyen bir sorun varsa, bağlantıları kopmuş kayıp dosyalar ortaya çıkmışsa, bunlar /lost+found altına atılır. Bağlantı kopması, inode gibi konulara girmek istemiyorum; biraz karmaşık. Kısaca özetlersek; kötü bir sistem kapanmasından sonra, olması gereken bazı dosyaları bulamıyorsanız, kayıp eşya bürosuna bakmanızda yarar var.

/media

CD-ROM, disket sürücü, flash bellek gibi çıkarılabilir aygıtlar buraya bağlanır. En basit tanımla, çıkarılabilir aygıtların, bağlantı noktası (mount point) olarak düşünebilirsiniz.

/mnt

/media klasörüne benzer. Temel farkı; çıkarılabilir aygıtlar yerine, dosya sistemleri veya donanım aygıtları için kullanılıyor oluşudur. Bağlama (mount) işlemi, herhangi bir dosya sistemini, işletim sisteminin kullanmasını sağlar. Nereye bağladığınız sizin tercihinizdir. Yani bir diski, /media veya /mnt klasörüne ya da bir başka yere bağlamanız fark etmeyecektir. Sadece genel kabul görmüş bazı bağlantı noktaları bulunuyor; /mnt klasörü de onlardan bir tanesi.

/opt

Dağıtımdan bağımsız ekstra yüklenen paketler için /opt klasörü kullanılmaktadır. Örneğin; Google Earth programını indirip kurmak istediğinizde, 'default' olarak kurulacağı nokta, /opt/google-earth adresidir.
Elbette ki bunu değiştirebilir ve size uygun gelen bir başka konuma yükleyebilirsiniz. Ancak daha önce söylediğimiz gibi bazı şeyler genel kabule dayanır. Ekstra yüklenen yazılımların, /opt adresine atanması da buna bir örnektir. Windows'taki C:\Program Files'i hatırlayalım;. programları buraya kurmak zorunlu değil; ama hemen hepsi buraya kuruluyor. Aynı mantık burada da geçerli.

/proc

/proc oldukça özel sanal bir dosya sistemidir. Bizim bildiğimiz anlamda fiziksel dosyalar bulundurmaz; sistem durumuna dair bilgi içeren sanal dosyaları vardır. Örneğin "cat /proc/swaps" yazarak sisteminizdeki takas dosyalarına dair bilgi alabilir ya da "cat /proc/cpuinfo" komutuyla işlemcinizin özelliklerini görebilirsiniz.
/proc klasörü içersindeki dosyalar, sadece sistem durumunu görüntülemek için kullanılmaz, gerektiğinde sistemde ayarlama yapmak için de kullanılabilir. Fakat son kullanıcılara hitap eden bir konu değildir.

/root

Unix'in ilk versiyonlarında root kullanıcısının kendine ait bir ev klasörü yoktu. Direkt olarak / (root klasörü) altında çalışırdı. Fakat zamanla bunun iyi bir yöntem olmadığı anlaşıldı ve root kullanıcısının ayrı bir klasöre sahip olması gerektiğine karar verildi. Diğer kullanıcılardan farklı olduğu için root, ev klasörü /home altında tutulmaz; /root klasörü olarak ayrılmıştır.

/sbin

Linux'ta normal kullanıcının kullanabileceği komutlarla, sistem kullanıcısının kullanabileceği komutlar ayrılmıştır. root tarafından kullanılacak bakım ve yönetim için kullanılan önemli programlar, /sbin altında tutulur. Daha az öneme sahip yönetim komutlarıysa, /usr/sbin klasöründedir. Eğer lokalde, yani kullandığınız makineye özgü yönetici (root) komutları bulunuyorsa, bunları da /usr/local/sbin altında bulabilirsiniz.

/usr

/root kullanıcısına benzer bir hikâye /usr için de söz konusudur. Unix ilk çıktığında, kullanıcılara ait ev klasörleri, /usr altında tutulurdu. Örneğin; "cagatay" isimli bir kullanıcının ev klasörü /usr/cagatay şeklindeydi. Bu yöntem zamanla değişti ve /home klasörü doğmuş oldu. /usr klasörü hâlâ çok önemli bir yapıdır ve işletim sisteminizde kullandığınız her şeyle ilişkisi bulunur.
/usr klasörünün önemi, yüklediğiniz programların buraya atılmasından kaynaklanır. /opt adresi işletim sistemi dışında gelen 3.parti programlar içindir. Fakat işletim sistemi aracılığıyla ya da paket yönetim sistemlerini kullanarak yüklediğiniz her şey, /usr altına aktarılır. Aynı zamanda yüklediğiniz programların çalışmak için ihtiyaç duyacağı kütüphane dosyaları, /usr/lib altındadır.
/usr ile ilgili söylenebilecek bir başka nokta da "local" klasörüdür. Linux, sunucu olarak birçok istemciye hizmet verebilecek bir işletim sistemidir. Bir Linux sunucu (server) kurarsanız, ona bağlanan yüzlerce istemci (client) olabilir. Her istemci bilgisayara, /usr altındaki programların ayrı ayrı yüklenmesi gerekmez; bir başka konumdan bu komutları çalıştırabilirsiniz. Ancak /usr altında bulunan "local" klasörü sadece kullandığınız makineye özeldir. Örneğin /usr/local/bin klasörü içinde bulunan bütün komutlar, direkt olarak kullandığınız makineye yüklenmiştir. /usr/bin komutları ise geneldir ve bir ağ üstündeki bütün makinelerden erişilebilir. "local" gördüğünüzde, bunun sadece sizin makinenize özel olduğunu bilin.

/var

Log dosyaları, e-posta ve yazıcı kuyrukları gibi değişken sistem bilgilerini barındırır. Sisteminize dair tutulan log'ları buradan görebilir; güvenlik durumunu buradan kontrol edebilirsiniz.

/tmp

Geçici dosyalar içindir. Birçok program, burayı geçici depolama alanı olarak kullanır. /tmp klasörünün içeriği genellikle KB'lar mertebesinde kalır ve genellikle işletim sistemi yeniden başlarken içindeki dosyalar silinir. /tmp klasörü altında bulunan dosyaları, ne yaptığınızdan emin değilseniz, kesinlikle silmemelisiniz! Sistem genelinde olmasa bile, program bazında problemler çıkabilir. Örneğin açık bir soket dosyasını sildiğinizde, onu kullanan programa ve kendinize sorun çıkartabilirsiniz.