30 Nisan 2014 Çarşamba

Alan Ekleme

Modelleri işlerken söylemiştik. Bir modeli oluşturduktan sonra o model bir kere okunur ve veritabanı oluşturulur. Yani model üzerinde yaptığınız değişiklikler veritabanına yansımayacaktır. Eğer yeni bir alan oluşturmak istersek veritabanını sildikten sonra Model üzerinde alanı ekleyerek veritabanını tekrardan oluşturabiliriz. Bu işlemin ne kadar can sıkıcı olduğunu görebiliyorsunuz. Özellikle veritabanı içerisinde çok fazla sayıda verileriniz varsa bu verileri kaybetmeniz anlamına gelir.
Şimdi model üzerine alan eklemeyi görelim. Doktor tablomuzda doktorun yaşını tutmuyorduk. Beraber yas alanını da ekleyelim. IntegerField türünden bir yaş alanı oluşturarak Doktor modeline ekleyeceğiz. Doktor modelini şu hale getirelim.
from django.core.validators import MaxValueValidator, MinValueValidator
class Doktor(models.Model):

 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 yas = models.IntegerField(blank=True,validators=[
  MaxValueValidator(70),
  MinValueValidator(30)
  ]
 )
 telefon = models.CharField(max_length=50,blank=True)
 eposta = models.EmailField(blank=True)

 def __unicode__(self):
  return u'%s , %s ,%s' % (self.adi,self.soyadi,self.eposta)
İlk satıra dikkat edin. Yaş alanının belli değerler arasında olmasını istiyoruz. Bunun için validators özelliğini kullandık. MaxValueValidator, MinValueValidator işlevlerini içe aktarmamız gerekiyor.
Yaş alanını Modele ekledik. Şimdi bu alanı veritabanına da eklemeliyiz. Bunun için Django kabuğunu açıyoruz ve şu işlemleri yapıyoruz.
python manage.py shell
>>> from django.conf import settings
>>> import sqlite3
>>> db = sqlite3.connect(settings.DATABASES['default']['NAME'])
>>> db.execute('ALTER TABLE yonetim_doktor ADD yas')
<sqlite3.Cursor object at 0x9fa0920>
>>> db.commit()
>>> db.close()
Veritabanına yaş alanını eklemiş olduk. Yönetim panelinden girerek kontrol edebilirsiniz. Doktor tablosunda yaş alanını göreceksiniz. Şimdi yaş alanını Form'a da ekleyelim. DoktorFormu'nun son hali şu şekilde olacaktır.
# -*- coding: utf-8 -*-
from django import forms
from django.core.validators import MaxValueValidator, MinValueValidator

class DoktorFormu(forms.Form):
 adi  =  forms.CharField(label="Adınız")
 soyadi  =  forms.CharField(label="Soyadınız")
 yas  =  forms.IntegerField(label="Yaşınız",required=False,validators=[
  MaxValueValidator(70),
  MinValueValidator(30)
  ]
  )
 telefon =  forms.CharField(label = "Telefon Numaranız:",required=False)
 eposta  = forms.EmailField(label="E-Posta Adresiniz",required=False)

 def clean_telefon(self):
  tel = self.cleaned_data['telefon']
  if tel != "":
   if len(tel) != 11:
    raise forms.ValidationError('Telefon numarasi 11 karakter olmalidir.')
  return tel

Şimdi kaydetme işlemi yapabilmek için doktor_ekleme görünümünde
doktor.soyadi = temiz_veri['soyadi']
satırı altına şu satırı ekleyelim;
doktor.yas = temiz_veri.get('yas')
Tarayıcıdan doktor-ekle sayfasını açarsanız, artık yeni görünüm şu şekilde olacaktır.
Şimdi son olarak doktor_listesi.html şablonunu da değiştirerek yaşı alanını da kullanıcılara gösterelim.
<table border="1">
    <tr><td><a href="/doktor-ekle/">Doktor Ekle</a></td></tr>
    <tr>
        <th>Sıra</th>
        <th><a href="?siralama=1">Adi<a/></th>
        <th><a href="?siralama=2">Soyadi</a></th>
        <th>Yaş</th>
        <th>Telefon</th>
        <th>E-Posta</th>
        <th>İşlemler</th>
    </tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ doktorlar.start_index|add:forloop.counter }}</td>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.yas }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>

        <td><a href="/doktor-ekle/?id={{ doktor.id }}">Düzenle </a><a href="/doktor-sil/?id={{ doktor.id }}">Sil</a></td>
    </tr>
    {% endfor %}

</table>

Kaynakça

27 Nisan 2014 Pazar

PyQt Sinyaller ve Slotlar

       Bir kullanıcı program üzerinde fare ya da klavyedeki herhangi bir tuşa tıkladığında sinyaller oluşur. Signal ve Slot Türkçe'ye Sinyal ve Yuva olarak çevrilmektedir. Bu Sinyal ve Yuvalar sayesinde program üzerinde meydana gelen olayları kontrol edebiliyoruz. Yani oluşan bu sinyali veya sinyalleri herhangi bir veya birden fazla metoda yönlendirerek o metot veya metotlardaki işlevlerin gerçekleştirilmesini sağlayabiliriz.

      Bir örnek üzerinden açıklamaya çalışalım. Alt alta bir Label ve bir Buton oluşturalım. Bu butona tıklandığında da Label üzerindeki yazıyı değiştirelim. Kodlarımız şu şekilde:

# !/usr/bin/env python
# -*- coding: cp1254 -*-

from PyQt4.QtGui import *
from PyQt4.QtCore import *
 
app = QApplication([])
 
window = QWidget()
window.setWindowTitle('PythonDersleri.com')
txtLabel = QLabel('Python Dersleri')
btnButton = QPushButton('Değiştir')
 
 
def changeTxtLabel():
    txtLabel.setText('Python Öğreniyorum')
 
window.connect(btnButton, SIGNAL('pressed()'), changeTxtLabel)
 
dizayn = QHBoxLayout()
dizayn.addWidget(txtLabel)
dizayn.addWidget(btnButton)
 
window.setLayout(dizayn)
window.show()
app.exec_()

Programı bu şekilde çalıştırdığınızda karşınıza şu şekilde bir pencere gelecektir:
Değiştir butonuna tıkladığınızda ise pencere şu şekilde değişecektir:

Şimdi de kodlarda neler yaptığımıza bir bakalım:
1. Satır = Yazdığımız kodların Python kodu olduğunu ve Python'un dizinini belirtiyoruz.
2. Satır = Türkçe karakterlerin desteklenmesini belirttik.
4. ve 5. Satır = Gerekli QT modüllerini programımıza dahil ettik.
7. Satır = Bir QApplication nesnesi oluşturduk.
9. Satır = Bir tane Widget oluşturduk. Butona tıklandığında oluşan sinyal bu widget üzerinden yakalanmaktadır.
10. Satır = Pencerenin başlığının "PythonDersleri.com" olacağını belirttik.
11. Satır = İçeriği "Python Dersleri" olan bir tane Label oluşturduk.
12. Satır = Üzerinde "Değiştir" yazan bir buton oluşturduk.
15. Satır = Burada bir fonksiyon tanımlanmıştır. Bu fonksiyon ile Label'a yeni text atanmaktadır.
18. Satır = btnButton isimli butona basıldığında pressed() sinyali yayınlanır. Bu sinyali window isimli bizim tarafımızdan oluşturulan QWidget'ın connect() metodu ile yakalamaktayız. 3. parametre olarak ise bu butona basıldığında hangi fonksiyonun çağrılacağını söylüyoruz. Bu şekilde butonumuza basıldığında QLabel'ımızın text'i değişecektir.
20. Satır = Bir adet QHBoxLayout oluşturulmakta. Bu layout ile label ve butonumuz yan yana sıralanacaktır. Alt alta sıralamak istiyorsanız QVBoxLayout kullanabilirsiniz.
21. ve 22. Satır = Oluşturduğumuz label ve buton bu layout içerisine yerleştiriyoruz.
24. Satır = Layout'u tanımladığımız window isimli Widget'a atıyoruz.
25. Satır = Window'u görünür yapıyoruz.
26. Satır = Uygulamamızı çalıştırıyoruz.

Alıştırmalar: 
1. Bir dizide sizin tarafınızdan tanımlanmış 10 adet eleman bulunmaktadır. Bu elemanlar her butona basıldığında label'e sırasıyla atanacaktır. Ayrıca üstte label olmak üzere buton ve label'imizin alt alta olması istenmektedir.

2. Çıkış isminde bir buton oluşturun ve bu butona tıklandığında programın kapatılmasını sağlayın.


Kaynaklar:
http://qt.comu.edu.tr/qtgiris/teksayfa/
http://gamzecukurluoz.blogspot.com.tr/2010/03/qt-nedir.html
http://qt-project.org/doc/qt-4.8/signalsandslots.html
Mustafa Başer - Python Kitabı

25 Nisan 2014 Cuma

Sayfalama

Web sayfalarında veri çekilirken tüm verilerin bir anda çekilerek yüklenmediğini fark etmişsinizdir. Belli sayıda veri çekilerek kullanıcıya gösterilir.Kullanıcının istemesi durumunda aynı şekilde tekrardan veriler veritabanından çekilerek kullanıcıya gösterilmeye devam edilir. Bu şekilde yapılmasının nedeni nedir? Çok fazla sayıda verinin tutulduğu bir veritabanı düşünürsek, verilerin bir anda çekilmesi veritabanına çok yük bindirir. Bu da sistemin yavaş çalışmasını sebep olur. Bunun yanında çok fazla verilerin aynı sayfada yüklenmesi göze de hoş gelmez. Bu tarz kötü durumlardan kaçınmak için sayfalama yapısı kullanılır.
Google'ın Sayfalaması
Google'da arama yaptığınız da milyonlarca sonuç bulunur. Hepsinin aynı sayfa üzerinde göründüğünü düşünsenize!
Django Sayfalama Yapısı
Django her şeyde olduğu gibi sayfalama yaparken de bize çok kolaylıklar sağlıyor. Django'nun sayfalamasını anlayabilmek için ilk önce kabuk üzerinde özelliklerine bakalım. Kabuğu nasıl açacağımızı biliyoruz.
python manage.py shell
İlk önce sayfalamanın Paginotor nesnesini içe aktaralım.
>>>from django.core.paginator import Paginator
Bir liste oluşturalım ve bu liste üzerinden sayfalamadan bahsedelim.
>>>universiteler = ['Sakarya','İstanbul','Bogozici','Hacettepe','Ege','Ankara']
Listeyi ve her sayfada kaç eleman olacağını Paginator işlevine parametre olarak gönderiyoruz.
>>>sayfalar = Paginator(universiteler,3)
Eleman sayısı;
>>> sayfalar.count
6
Sayfa sayısı;
>>> sayfalar.num_pages
2
Sayfa aralığı;
>>> sayfalar.page_range
[1, 2]
Sayfaları almak;
>>> sayfa1 = sayfalar.page(1)
>>> sayfa1
<Page 1 of 2>
>>> sayfa2 = sayfalar.page(2)
>>> sayfa2
<Page 2 of 2>
Olmayan bir sayfayı almaya çalışırsanız, hata ile karşılaşırsınız. Sayfa numaraları 0'dan değil 1'den başlar.
>>> sayfa3 = sayfalar.page(3)
Traceback (most recent call last):
...
>>>> sayfa3 = sayfalar.page(0)
Traceback (most recent call last):
...
Aldığımız sayfalardaki elemanlar;
>>> sayfa1.object_list
['Sakarya', '\xc4\xb0stanbul', 'Bogozici']
>>> sayfa2.object_list
['Hacettepe', 'Ege', 'Ankara']
Türkçe karakter sorununa takılmayın. Tarayıcı da bu problemleri almayacağız.
Sonraki sayfa var mı?
>>> sayfa1.has_next()
True
>>> sayfa2.has_next()
False
Önceki sayfa var mı?
>>> sayfa2.has_previous()
True
>>> sayfa1.has_previous()
False
Başka sayfalar var mı?
>>> sayfa2.has_other_pages()
True
Sayfadaki ilk ve son elemanın indisi;
>>> sayfa2.start_index()
4
>>> sayfa2.end_index()
6
Sayfa numarası
>>> sayfa2.number
2
Sayfalamanın Görünümler ile Kullanılması
Şimdi gelelim asıl konumuza. Doktorlar listesini sayfalama yaparak gösterelim. İlk önce Doktor_listesi görünümünü düzenleyelim.
from django.core.paginator import Paginator
def Doktor_listesi(request):
 siralama = 'adi'
 kiriter = request.GET.get('siralama')
 sayfa = request.GET.get('sayfa',1)
 if kiriter:
  siralamaKriteleri = {
   '1':'adi',
   '2':'soyadi'
  }
  if kiriter in siralamaKriteleri:
   siralama = siralamaKriteleri[kiriter]

 doktorlar_tum = Doktor.objects.order_by(siralama)
 doktorlar_sayfalari = Paginator(doktorlar_tum,5)
 doktorlar = doktorlar_sayfalari.page(int(sayfa))
 return render_to_response('doktor_listesi.html',locals())
Paginator işlevini içe dahil etmeyi unutmayın. Her sayfada 5 doktor göstereceğimiz şekilde düzenleme yaptık. sayfa değişkenini GET metodu ile aldığımıza dikkat edin. Eğer bir değer atanmamışsa varsayılan olarak 1 olacaktır. Şablonu da yeniden düzenleyelim.
<table border="1">
    <tr><td><a href="/doktor-ekle/">Doktor Ekle</a></td></tr>
    <tr>
        <th>Sıra</th>
        <th><a href="?siralama=1">Adi<a/></th>
        <th><a href="?siralama=2">Soyadi</a></th>
        <th>Telefon</th>
        <th>E-Posta</th>
        <th>İşlemler</th>
    </tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ doktorlar.start_index|add:forloop.counter }}</td>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>
        <td><a href="/doktor-ekle/?id={{ doktor.id }}">Düzenle</a><a href="/doktor-sil/?id={{ doktor.id }}">Sil</a></td>
    </tr>
    {% endfor %}

</table>

{% if doktorlar.has_previous %}
    <a href="?sayfa={{ doktorlar.previous_page_number }}">Önceki</a>
{% endif %}

{{ doktorlar.number }}

{% if doktorlar.has_next %}
    <a href="?sayfa={{doktorlar.next_page_number }}">Sonraki</a> 
{% endif %}
Artık doktorlar listesinin görünümü aşağıdaki gibi olacaktır. Tam da istediğimiz gibi değil mi ? Django bizim için her şeyi halletti.
Google'ınki gibi bir sayfalama yapmak isterseniz şablonda eklediklerimizi silerek şu satırı ekleyebilirsiniz.
{% for i in doktorlar.paginator.page_range %}
    {% if doktorlar.number == i %}
    <a href="?sayfa={{i}}" class="secili">
    {% else %}
    <a href="?sayfa={{i}}">
    {% endif %}
        {{i}}</a>
{% endfor %}
Burada secili class'ı o anda bulunulan sayfanın numarasına atanmıştır. Bunu kullanarak stil verebiliriz. Bu şekilde kullanıcı hangi sayfada olduğunu rahatça anlayabilir.
Kaynakça

19 Nisan 2014 Cumartesi

Kayıt Sıralama

Kullanıcıya kayıtları gösterirken, kullanıcının istediği bir alan üzerinde sıralama yapmasına izin verebiliriz. Daha önce doktorları listelediğimiz uygulamada kullanıcıya bazı alanlara göre listeleme imkanı sunalım. Bunun için doktor_listesi.html şablonundaki başlıkları şu şekilde değiştirelim.
    <tr>
        <th>Sıra</th>
        <th><a href="?siralama=1">Adi<a/></th>
        <th><a href="?siralama=2">Soyadi</a></th>
        <th>Telefon</th>
        <th>E-Posta</th>
        <th>İşlemler</th>
    </tr>
Dikkat ettiyseniz parametreleri GET metodu ile gönderiyoruz. Şimdi Doktor_listesi görünümünü sıralama olanağı verebileceğimiz şekilde değiştirelim.
def Doktor_listesi(request):
 siralama = 'adi'
 kiriter = request.GET.get('siralama')
 if kiriter:
  siralamaKriteleri = {
   '1':'adi',
   '2':'soyadi'
  }
  if kiriter in siralamaKriteleri:
   siralama = siralamaKriteleri[kiriter]

 doktorlar = Doktor.objects.order_by(siralama)
 return render_to_response('doktor_listesi.html',locals())
Burada yaptığımız işlem; eğer kullanıcı bir parametre girmiş ise girdiği parametreye göre girmediyse varsayılan olarak adi alanına göre sıralama yaptırdık. Burada kiriter değişkenini şablona gönderiyoruz. Bu değişkene göre alan adlarına farklı stiller uygulayarak belli olmasını sağlayabilirsiniz.
Tersten Sıralama
Hatırlarsanız Modeller'i işlerken tersten sıralama yapmak için alan adı başına - işareti koymamız gerektiğin söylemiştik. Verdiğimiz örnekte tersten sıralama yapmak isterseniz şu şekilde kullanabilirsiniz.
doktorlar = Doktor.objects.order_by("-"+siralama)
Kaynakça
  • Mustafa Başer Django Kitabı

18 Nisan 2014 Cuma

Merhaba PyQt

       Bir programlama dili öğrenilirken ilk yazılan kod "Merhaba Dünya" çıktısı veren kodlardır. Biz de burada ilk olarak PyQt'de bunu uygulayacağız. Ancak biraz farklılık yapıp "Merhaba Dünya" yerine "Merhaba PyQt" diyelim. Öncelikle kodu yazalım ve kodlar üzerinden anlatmaya devam edelim.

# !/usr/bin/env python
# -*- coding: cp1254 -*-

from PyQt4.QtGui import *

uygulama = QApplication([])
etiket = QLabel('Merhaba PyQt')
etiket.show()
uygulama.exec_()

Bu kodu çalıştırdığınız da şekildeki gibi bir pencere açılacaktır.

Şimdi bu program için yazdığımız kodlarda ne yaptığımıza bakalım. İlk üç satır ile gerçekleştirilen işlemlerin ne anlam ifade ettiğini bu kısma gelmeden önce biliyor olmanız gerekiyor. Bunlara değinmiyoruz.
Bir sonraki satırda bir Qt uygulaması başlattık. Qt uygulamalarının her biri QApplication nesnesinden oluşmaktadır. Parantezler arasında da nesneye gönderilecek argümanlar eklenir. Komut satırından gönderilen parametreler bu şekilde gönderilmektedir. Burada biz herhangi bir parametre kullanmadık.

5. satırda Qt'ye ait etiket isminde bir etiket oluşturduk, bu etikete parametre olarak verdiğimiz 'Merhaba PyQt' ise bu etiketin içeriğini yani içinde gösterilecek olan metni temsil etmektedir.
Etiket, buton gibi kullandığımız parçacıklara Widget denilmektedir.
Bir sonraki satırda ise oluşturduğumuz bu etiketin görünür olmasını sağladık.

Son satırda da uygulamamızın başlamasını istedik. Bu kod sonsuz bir döngüyü ifade etmektedir. Yani kod bu kısımda baştan tekrar çalışmaktadır. Bu sayede fare ve klavye gibi girdi cihazlarının sinyalleri dinlenebilmekte ve uygulamada kullanılabilmektedir.


Burada yazmış olduğumuz program kullanıcı denetimden yoksundur. Bu yüzden normal bir Grafiksel Kullanıcı Arayüzüne sahip sayılmaz. Tek yapılan iş etiket içeriğinin gösterilmesidir. Oysaki Grafiksel Kullanıcı Arayüzüne sahip bir program kullanıcısı tarafından gelecek girdilere tepki verebilir şekilde olmalıdır.


Etiketlere parametre olarak verdiğimiz metinler için boyut, renklendirme gibi özellikler için HTML kodları kullanılabilmektedir. Örneğin bu yazımızın rengini kırmızı yapalım ve boyutunu ise büyütelim. Bunun için etiketi oluşturduğumuz kodu aşağıdaki gibi düzenlememiz yeterli olacaktır.

etiket = QLabel('Merhaba PyQt')

Bu şekilde düzenledikten sonra çalıştırdığınızda ise aşağıdaki gibi bir çıktı oluşacaktır.

11 Nisan 2014 Cuma

Python RSA Modülü ile Kriptolama

Bu yazımızda Python'da rsa modülünü kullanarak nasıl kriptolama yapabileceğinizden bahsedeceğiz. Kullanımı oldukça basit. Ama bunun için ilk önce rsa modülünün kurulması gerekiyor. Bunun için şu komutu vermeniz yeterli.
sudo pip install rsa
Modülü kurduktan sonra kullanımı oldukça basit. Şu örneği inceleyelim.
import rsa

(sifrelemeAnahtari,sifreCozmeAnahtari) = rsa.newkeys(512)

mesaj = 'Python Dersleri'

sifreliMetin = rsa.encrypt(mesaj,sifrelemeAnahtari)
CozulmusMetin = rsa.decrypt(sifreliMetin,sifreCozmeAnahtari)
print sifreliMetin
print CozulmusMetin
##Örnek çıktı
4�c�*)�� �G�7l��A ��ƚm�p E��P��:n��� >
Python Dersleri
  • 1.satır : rsa modülü içe aktarıldı.
  • 3.satır : rsa modülü ile kriptolama yapabilmek için anahtarlar üretildi. Buradaki 512 bit sayısını belirtir.
  • 7.satır : encrypt metodu ile şifreleme yapılır. Şifreleme yapılırken oluşturulan anahtar kullanılır.
  • 8.satır : decrypt medou ile şifrelenen metin çözülür. Çözülme yapılırken oluşturulan anahtar kullanılır.
Eğer istersek bildiğimiz kriptolama algoritmalarını kullanabiliriz. Örneğin bir metni sha512 ile kriptolayalım. Bunun için
import rsa

(sifrelemeAnahtari,sifreCozmeAnahtari) = rsa.newkeys(752)

mesaj = 'Python Dersleri'

sifreliMetin = rsa.sign(mesaj,sifreCozmeAnahtari,'SHA-512')
print sifreliMetin
#Örnek Çıktı
���e�����/����Qb!n7� _|7VT �/��q���i Km⢐�ʝ���r�ȁq ���o 3=� �ŧ�16E�� ��6�E�] �l"�~�R=�
Bu yöntem için sign metodunu kullanıyoruz. SHA-512 ile kriptolama yapabilmek için bit uzunluğunun en az 752 olması gerekmektedir.
rsa modülü hakkında çok daha ayrıntılı bilgilere http://stuvel.eu/rsa adresinden ulaşabilirsiniz.

10 Nisan 2014 Perşembe

FTP Sunucu Servisi Dosya/Dizin Tespit Çalışması

Gerek sistem yöneticileri için gerekse sızma testi uzmanları için ağ içerisindeki FTP sunucu servislerinin tespit edilerek içeriklerinin araştırılması gerekebilmektedir. Windows ağlarındaki paylaşımları tespit ederek belirtilen yapılandırma dosyasına göre veri taraması gerçekleştiren projeye https://github.com/galkan/depdep adresinden erişim sağlanabilir. Bunun için öncelikle gerekli ağ içerisindeki FTP sunucu servisleri için keşif çalışması gerçekleştirilmelidir. Bu amaçla en çok kullanılan yazılımlardan olan nmap ile ön tanımlı 21/tcp portu için tarama gerçekleştirerek mecut FTP sunucu servisleri için keşif adımı gerçekleştirilmelidir. Bu işlem 192.168.1.0 ağı için aşağıda gösterildiği şekilde gerçekleştirilebilir.

# nmap -n -PN -sS -p 21 --open 192.168.1.0/24

Bu amaçla aşağıda gösterilen betik kullanılabilir. FTP servisi için gerekli modül olarak ftputil kullanılmıştır. Daha fazla ayrıntı için https://pypi.python.org/pypi/ftputil/2.2.3 adresine göz atılabilir.

#!/usr/bin/python

try:
       import sys
       import ftplib
except ImportError,e:
        import sys
        sys.stdout.write("%s\n" %e)
        sys.exit(1)


class FTP:
  result = []

  def __init__(self):
    """
     Create instance for ftp ...
    """

    self.ftp = ftplib.FTP()


  def is_directory(self, ftp, directory):
    """
     Determine whether given parameter is directory or not ...  
    """

    try:
      ftp.cwd(directory)
    except:
            return False

    ftp.cwd("..")
    return True



  def traverse(self, ftp):
    """
     Traverse ftp and add results to the result list ...   
    """

    dirs = ftp.nlst()
        for item in (path for path in dirs if path not in ('.', '..')):
      if self.is_directory(ftp, item):
              try:
                   ftp.cwd(item)
                   self.traverse(ftp)
                   ftp.cwd('..')
              except Exception, e:
          pass

      else:
        ret = "%s/%s"% (ftp.pwd(), item)
        FTP.result.append(ret)



  def run(self, ip_addr, port, timeout, username = None , passwd = None):
    """
     Run ftp for given ip address and credentials ...
    """ 

    try:
      self.ftp.connect(ip_addr, port , timeout)
    except:
      return False
  
 
    try:
      if username and passwd is not None:
        self.ftp.login(username, passwd)
      else:
        self.ftp.login()
    except:
      return  False   

    self.ftp.set_pasv(True)
    self.ftp.cwd("/")
  
        self.traverse(self.ftp)

    return FTP.result


if __name__ == "__main__":
 ip = "192.168.37.37"
 port = 21
 timeout = 3
 username = "user"
 password = "password"

 ftp = FTP()
 for val in ftp.run(ip, port, timeout, username, password):
  print val




Betik ftp_traversing.py isimli dosyaya kaydediliğ aşağıdaki şekilde çalıştırıldığıdan elde edilecek çıktı aşağıdakinne benze şekilde olmaktadır.

# ./ftp_traversing.py
/dizin1/dizin2/dosya1
/dizin1/dizin3/dosya2
/dizin4/dizin5/dosya3
/dizin4/dizin6/dosya4
/dizin4/dizin7/dosya5
/dizin8/dizin9/dosya6




8 Nisan 2014 Salı

Kayıt Düzenleme ve Silme

Kayıt Düzenleme
Bir önceki konuda nasıl kayıt ekleyebileceğimizi gördük. Şimdi eklediğimiz bir kaydı nasıl düzenleyebiliriz? bunu inceleyeceğiz. Düzenleme işlemi yapabilmek için form elemanlarının varsayılan değerlerinin alanlara göre doldurulması gerekiyor. Hatırlarsanız bir form elemanın varsayılan değerini initial özelliği ile belirleye biliyorduk. Şimdi bu özelliği kullanarak doktorlar için oluşturduğumuz form ekleme formunu düzenleyelim. Eğer kullanıcı var olan bir kaydı düzenlemek isterse düzenleme, yeni kayıt eklemek isterse yeni kayıt ekleyelim.
İlk önce doktorları listelediğimiz şablonu değiştirerek form-ekle adresine gideceği butonu koyalım.
### doktor_listesi.html
<table border="1">
    <tr><th>Sıra</th><th>Adi</th><th>Soyadi</th><th>Telefon</th><th>E-Posta</th><th>İşlem</th></tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>
        <td><a href="/doktor-ekle/?id={{ doktor.id }}">Düzenle</a></td>
    </tr>
    {% endfor %}

</table>
Adres çubuğuna http://localhost:8000/doktorlar/ yazdığımız da şu şekilde bir çıktı alacağız.
doktor_listesi.html şablonundaki 12.satıra inceleyelim. Burada GET metodunu kullanarak düzenleyeceğimiz verinin id numarasını alacağız. Veritabanından aldığımız id numarasına ait verileri getirerek formun varsayılan değeri yapacağız. Şimdi bu işlemleri yapacağımız doktor_ekleme görünümünü oluşturalım.
def doktor_ekleme(request):
 doktorID = request.GET.get('id')

 if doktorID:
  try:
   doktor = Doktor.objects.get(id=doktorID)
  except:
   return HttpResponse(u'Aradığınız doktor bulunamadı. ID= %s' % (doktorID))

 if request.method == 'POST':
  form = DoktorFormu(request.POST)

  if form.is_valid():
   temiz_veri = form.cleaned_data
   if not doktorID: doktor = Doktor()
   doktor.adi= temiz_veri['adi']
   doktor.soyadi = temiz_veri['soyadi']
   doktor.telefon = temiz_veri.get('telefon')
   doktor.eposta = temiz_veri.get('eposta')
   doktor.save()
   return HttpResponseRedirect('/doktorlar/')
 else:
  if doktorID:form = DoktorFormu(initial=doktor.__dict__)
  else: form = DoktorFormu()

 return render_to_response('form.html',
        {'form':form,'baslik':'Öğretim Elemanı İşlemleri'},
        context_instance = RequestContext(request))

Daha önce söylemiştik: GET metodu bir sayfa yenilendiğinde her zaman çalışır. Yani POST metodundaki gibi belirtmemiz gerekmiyor. Şimdi doktor_ekleme görünümünün adımlarını inceleyelim.
  • 2.satır: GET metodu ile id parametresinin değerini alıyoruz.
  • 4.satır: id parametresi ile bir değer gönderilmiş mi ? kontrol ediyoruz.
  • 6.satır: Eğer id gelmiş ise, o id'e ait doktoru veritabanında çekiyoruz.
  • 8.satır: Veritabanında doktoru çekerken eşleşme yapılamazsa öyle bir doktor olmadığını kullanıcıya bildiriyoruz.
  • 10.satır: Sayfanın Post edildiğinin kontrolünü yapıyoruz. Eğer POST edilmemişse 22.satıra atlanılacaktır.
  • 11.satır: Daha önce oluşturduğumuz DoktorFormu içerisine POST ile gelen değerleri gönderiyoruz.
  • 13.satır: DoktorFormu'na gönderilen değerlerin Form'un istediği değerler ile uyuşup uyuşmadığını kontrol ediyoruz.
  • 14.satır: Gelen verileri temizleyerek temiz_veri değişkenine atıyoruz.
  • 15.satır: Eğer doktorID boş ise yani id parametresine bir değer atanmamış ise doktor değişkenine Doktor() veritabanına eşitleyerek yeni veri ekleyeceğimizi bildiriyoruz. Eğer doktorID dolu ise atama işlemini zaten 6.satırda yapmıştık.
  • 16-19.satır Bu satırlar arasında veritabanındaki alanlara atama işlemini yapıyoruz. Zorunlu olmayan alanları hata olmaması için Post.get metodu ile aldığımıza dikkat edin. Bunu daha önce de söylemiştik.
  • 20.satır: Son atadığımız alanları veritabanına kaydediyoruz.
  • 22.satır Eğer görünüme POST edilerek gelinmedi ise bu blok çalışacaktır.
  • 23.satır: Eğer id parametresine değer atandı ise o değere sahip doktoru bularak doktor değişkenine atmıştık. Burada initial özelliğini kullanarak DoktorForm'u alanlarına varsayılan değer olarak doktor içerisindeki değerleri atıyoruz. Eğer id parametresine değer atanmadı ise boş bir DoktorFormu gönderiyoruz.
  • 26.satır: Şablon'a oluşturduğumuz formu gönderiyoruz.

Kayıt Silme
Kayıt düzenlemede olduğu gibi kayıt silme işlemi yapmadan önce doktor-listesi şablonuna sil butonunu koyalım.
###doktor_listesi.html
<table border="1">
    <tr><th>Sıra</th><th>Adi</th><th>Soyadi</th><th>Telefon</th><th>E-Posta</th><th>İşlem</th></tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>
        <td><a href="/doktor-ekle/?id={{ doktor.id }}">Düzenle  </a><a href="/doktor-ekle/?id={{ doktor.id }}&sil=1">Sil</a></td>
    </tr>
    {% endfor %}

</table>
Adres çubuğuna http://localhost:8000/doktorlar/ yazdığımız da çıktı şu şekilde değişecek.
Şimdide doktor_ekleme görünümünü düzenleyelim.

def doktor_ekleme(request):
 doktorID = request.GET.get('id')

 if doktorID:
  try:
   doktor = Doktor.objects.get(id=doktorID)
  except:
   return HttpResponse(u'Aradığınız doktor bulunamadı. ID= %s' % (doktorID))

        ###silme işlemi için ekliyoruz
 if request.GET.get('sil'):
  doktor.delete()
  return HttpResponseRedirect('/doktorlar/')

 if request.method == 'POST':
  form = DoktorFormu(request.POST)

  if form.is_valid():
   temiz_veri = form.cleaned_data
   if not doktorID: doktor = Doktor()
   doktor.adi= temiz_veri['adi']
   doktor.soyadi = temiz_veri['soyadi']
   doktor.telefon = temiz_veri.get('telefon')
   doktor.eposta = temiz_veri.get('eposta')
   doktor.save()
   return HttpResponseRedirect('/doktorlar/')
 else:
  if doktorID:form = DoktorFormu(initial=doktor.__dict__)
  else: form = DoktorFormu()

 return render_to_response('form.html',
        {'form':form,'baslik':'Öğretim Elemanı İşlemleri'},
        context_instance = RequestContext(request))
Eğer sil parametresine değer ataması yapıldıysa doktorID ait doktor'u veritabanından siliyoruz. Son olarak doktorlar sayfasına doktor ekleyebilmek için Doktor Ekle butonu ekleyelim. Bunun için doktor_listesi.html şablonun istediğiniz bir yerine şu satırı ekleyin.
<a href="/doktor-ekle/">Doktor Ekle</a>
Yaptığımız uygulamalarda tüm işlemleri tek bir görünüm üzerinden yaptık. Eğer isterseniz farklı görünümler üzerinden de yapabilirsiniz. Silme işlemini farklı bir görünüm ile yapalım.
İlk önce urls.py dosyasına şu satırı ekleyelim.
url(r'^doktor-sil/',yonetim.views.doktor_silme),
Daha sonra doktor_listesi.html şablonunu değiştirelim.
<table border="1">
    <tr><th>Sıra</th><th>Adi</th><th>Soyadi</th><th>Telefon</th><th>E-Posta</th><th>İşlem</th></tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>
##doktor-sil sayfasına yönlendirdik.
        <td><a href="/doktor-ekle/?id={{ doktor.id }}">Düzenle  </a><a href="/doktor-sil/?id={{ doktor.id }}">Sil</a></td>
    </tr>
    {% endfor %}

</table>
Son olarak da doktor_silme görünümünü oluşturalım.
def doktor_silme(request):
 doktorID = request.GET.get('id')
 if doktorID:
  try:
   doktor = Doktor.objects.get(id=doktorID)
  except:
   return HttpResponse(u'Aradığınız doktor bulunamadı. ID= %s' % (doktorID))

 doktor.delete()
 return HttpResponseRedirect('/doktorlar/')
Aynı işlemi farklı görünüm üzerinden yapmış olduk. Sizde güncelleme işlemini farklı görünüm üzerinden yapmayı deneyin.
Kaynakça
  • Mustafa Başer Django Kitabı

5 Nisan 2014 Cumartesi

Gelelim asıl meselemize. Formu Django imkanlarından yararlanarak basit bir şekilde oluşturduk. Şimdi bunu görünümlerde kullanarak kullanıcıya göstermemiz gerekiyor. Daha önceden yaptığımız veritabanına Doktor ekleme işlemini artık Django Formlarını kullanarak yapalım.
İlk önce görünümü oluşturalım.
from yonetim.forms import *
def doktor_ekleme(request):
 if request.method == "POST":
  form = DoktorFormu(request.POST)
  if form.is_valid():
   temiz_degerler = form.cleaned_data
   doktor = Doktor(adi=temiz_degerler['adi'],soyadi=temiz_degerler['soyadi'],
       telefon=temiz_degerler.get('telefon'),eposta=temiz_degerler.get('eposta'))
   doktor.save()
   return HttpResponseRedirect('/doktorlar/')
  else:
   return render_to_response('form.html',{'form':form,'baslik':'Doktor Ekleme'},context_instance = RequestContext(request))
 else:
  form = DoktorFormu()
  return render_to_response('form.html',{'form':form,'baslik':'Doktor Ekleme'},context_instance = RequestContext(request))
Burada eğer Post edilmiş ise işlem yapıyoruz edilmemişse formu form.html şablonuna yönlendiriyoruz.
form = DoktorFormu(request.POST) satırı ile formdan gelen verileri doğrudan oluşturduğumuz DoktorFormu sınıfına yolluyoruz.
is?valid() ile kontrol ediyoruz eğer herhangi bir sıkıntı yoksa veritabanına kaydediyoruz. Girilen değerler de problem varsa tekrardan form sayfasına yönlendiriyoruz.
temiz_degerler = form.cleaned_data satırı ile gelen verileri güvenlik için temizledik ve temizlediğimiz değerler üzerinden işlem yaptık.
Zorunlu olmayan verileri temiz_degerler.get('telefon') şeklinde aldık. Eğer bu şekilde değilde doğrudan alırsak kullanıcı alanları doldurmazsa hata ile karşılaşırız. Bunu engellemek için bu şekilde kulandık.
Şimdi genel bir form tasarlayalım. yonetim/sablonlar içerisine form.html adında şablon oluşturuyoruz.
<!DOCTYPE html>
<html>
<head>
    <title>{{ baslik }}</title>
     <link rel="stylesheet" type="text/css" href="/static/base.css">
</head>
<body>
<h1>{{ baslik }}</h1>
{% if form.errors %}
    <span style="color: red">
        Hataları düzeltin :
    </span>
{% endif %}

<form method="POST">
    {% csrf_token %}
    <table border="1">
            {{ form }}
     <tr><td></td><td><input type="submit" value="Gönder" /></td></tr>
    </table>

</form>


</body>
</html>
Gördüğünüz gibi gönderdiğimiz formu doğrudan yazdırdık. Eğer bir hata varsa kontrolünü forms.error ile yakalayarak kullanıcıyı uyardık. Eğer kullanıcı verileri yanlış doldurarak gönderirse şu şekilde bir çıktı ile karşılaşacak.
Django formu oluştururken etiketleri alan isimlerine göre kendisi belirliyor. Biz istersek kendi etiketlerimiz oluşuturabiliriz. Bunun için DoktorFormu sınıfını değiştirelim.
class DoktorFormu(forms.Form):
 adi  =  forms.CharField(label="Adınız")
 soyadi  =  forms.CharField(label="Soyadınız")
 telefon =  forms.CharField(label = "Telefon Numaranız:",required=False)
 eposta  = forms.EmailField(label="E-Posta Adresiniz",required=False)
Sayfayı yenilediğiniz zaman kendi etiketlerinizi göreceksiniz. Hataları alan üstlerinde göstermek pek hoş olmadı bunun için şablonu biraz daha değiştirelim ve hataları yanında gösterelim.
<!DOCTYPE html>
<html>
<head>
    <title>{{ baslik }}</title>
     <link rel="stylesheet" type="text/css" href="/static/base.css">
</head>
<body>
<h1>{{ baslik }}</h1>
{% if form.errors %}
    <span style="color: red">
        Hataları düzeltin :
    </span>
{% endif %}

<form method="POST">
    {% csrf_token %}
    <table border="1">

        {% for f in form %}
            {% if f.errors %}<tr >{%else %}<tr>{% endif %}
            <th>{{ f.label }}</th>
            <th>{{ f }}</th>
            {% if f.errors %}<td style="color: red">{{ f.errors }}</td>{% endif %}
            </tr>
        {% endfor %}

     <tr><td></td><td><input type="submit" value="Gönder" /></td></tr>
    </table>

</form>


</body>
</html>
Burada alanları tek tek yazdırdık. Eğer o alanda bir problem varsa yanına yeni bir sütün daha ekleyerek hatayı gösterdik. Çıktımız şu şekilde olacak.
Bu işlem bu kadar. Şimdi küçük bir bilgi verelim. Elimizde bulunan bir form nesnesini istediğimiz bir başka nesneye dönüştürebilmek için widget özelliğini kullanabiliriz.
class DoktorFormu(forms.Form):
 adi  =  forms.CharField(label="Adınız")
 soyadi  =  forms.CharField(label="Soyadınız")
 telefon =  forms.CharField(label = "Telefon Numaranız:",required=False)
 eposta  = forms.EmailField(label="E-Posta Adresiniz",required=False)
 mesaj =  forms.CharField(widget=forms.Textarea)
Bu şekilde değiştirdikten sonra form içerisinde bir textarea nesnesi göreceksiniz.
Kaynakça

2 Nisan 2014 Çarşamba

Django Form Yapısı

Bir önceki bölümde Formların şablonlar içerisinde kullanarak görünümler ile bağlantısını sağlamıştık. Bu bölümde ise Django'nun bizim için sağladığı kolaylıklardan olan ve form oluşturma işini Django'nun hallettiği form yapısından bahsedeceğiz. Yani biz modelleri oluştururken yaptığımız gibi nasıl bir form istediğimizi söyleyeceğiz. Django formu bizim için oluşturacak.
Form oluşturma işlemini uygulama içerisindeki herhangi bir Python dosyası içerisinde yapabilirsiniz. Ama biz geleneğe bağlı kalarak forms.py dosyası içerisinde oluşturacağız. Şimdi daha önceki hastahane projemiz üzerinden gidiyoruz.
yonetim/forms.py dosyasını oluşturarak içerisine kodları yazıyoruz.
from django import forms

class DoktorFormu(forms.Form):
 adi  =  forms.CharField()
 soyadi  =  forms.CharField()
 telefon =  forms.CharField(required=False)
 eposta  = forms.EmailField(required=False)
Burada ilk olarak django programından formsu içe aktarıyoruz. İçe aktarma yaptığımıza göre artık fonksiyonlarını kullanabiliriz. Oluşturduğumuz form sınıfının model sınıfı oluşturmaya çok benzediğini fark etmişsinizdir. Burada dikkat etmemiz gereken form alanlarına isim verirken modellerimizdeki isimler ile aynı olması gerektiğidir. telefon ve eposta alanlarını oluştururken kullandığımız required=False özelliği isteğe bağlı olduğunu belirtir.
Django kabuğunu açarak formumuzun nasıl olduğunu kontrol edelim.
>>> from yonetim.forms import *
>>> doktorForm = DoktorFormu()
>>> print doktorForm
<tr><th><label for="id_adi">Adi:</label></th><td><input id="id_adi" name="adi" type="text" /></td></tr>
<tr><th><label for="id_soyadi">Soyadi:</label></th><td><input id="id_soyadi" name="soyadi" type="text" /></td></tr>
<tr><th><label for="id_telefon">Telefon:</label></th><td><input id="id_telefon" name="telefon" type="text" /></td></tr>
<tr><th><label for="id_eposta">Eposta:</label></th><td><input id="id_eposta" name="eposta" type="email" /></td></tr>
Django bizim için label(etiket) ve input taglarını kullanarak formu oluşturdu.Buradaki etiketler alan isimlerinden çıkartılır.Django formları tarayıcıda düzgün görünebilmesi için tablo yapısını kullanarak oluşturdu. Ama dikkat etmelisiniz form açma(<table>) ve kapama(</table>) etiketleri bulunmamaktadır. Bu etiketleri şablon içerisinde kendimiz ekleyeceğiz. Formları oluşturmanın tek yolu tablo yapısı değil. Django bize bir kaç alternatif sunar.
Form elemanlarını satır satır bastıralım.
>>> from yonetim.forms import *
>>> doktorForm = DoktorFormu()
>>> print doktorForm
<tr><th><label for="id_adi">Adi:</label></th><td><input id="id_adi" name="adi" type="text" /></td></tr>
<tr><th><label for="id_soyadi">Soyadi:</label></th><td><input id="id_soyadi" name="soyadi" type="text" /></td></tr>
<tr><th><label for="id_telefon">Telefon:</label></th><td><input id="id_telefon" name="telefon" type="text" /></td></tr>
<tr><th><label for="id_eposta">Eposta:</label></th><td><input id="id_eposta" name="eposta" type="email" /></td></tr>
Veya form elemanlarını liste şeklinde de alabiliriz.
>>> print doktorForm.as_ul()
<li><label for="id_adi">Adi:</label> <input id="id_adi" name="adi" type="text" /></li>
<li><label for="id_soyadi">Soyadi:</label> <input id="id_soyadi" name="soyadi" type="text" /></li>
<li><label for="id_telefon">Telefon:</label> <input id="id_telefon" name="telefon" type="text" /></li>
<li><label for="id_eposta">Eposta:</label> <input id="id_eposta" name="eposta" type="email" /></li>
Python bizim için her şeyi biz nasıl istersek o şekilde yapıyor. Oluşturduğumuz bir form içerisinden istediğimiz bir elemanı çekebiliriz.
>>> print doktorForm['adi'].label
Adi
>>> print doktorForm['adi']
<input id="id_adi" name="adi" type="text" />
Varsayılan Değerler
Eğer bir form elemanın sayfa yüklenirken varsayılan bir değer ile yüklenmesini istiyorsanız bunu da sağlayabilirsiniz. Bunun için initial özelliğini kullanacağız.
>>> varsayilan = {'adi':'Adiniz. Bos birakilamaz.'}
>>> form = DoktorFormu(initial=varsayilan)
>>> print form
<tr><th><label for="id_adi">Adi:</label></th><td><input id="id_adi" name="adi" type="text" value="Adiniz. Bos birakilamaz." /></td></tr>
<tr><th><label for="id_soyadi">Soyadi:</label></th><td><input id="id_soyadi" name="soyadi" type="text" /></td></tr>
<tr><th><label for="id_telefon">Telefon:</label></th><td><input id="id_telefon" name="telefon" type="text" /></td></tr>
<tr><th><label for="id_eposta">Eposta:</label></th><td><input id="id_eposta" name="eposta" type="email" /></td></tr>
Artık adi etiketinin value değerinin dolu olduğunu görebilirsiniz.
Formların Kontrolü
Formlar doldurulduktan sonra bizim istediğimiz standartlara göre doldurulup doldurulmadığını kontrol edebiliriz. Eğer bu kontrolü yapmaz isek aldığımız değerleri veritabanına kaydederken standartlara uygun olmadığı için hata ile karşılaşırız. Kontrol etmek için is_valid() metodunu kullanacağız.
>>> gonderilenler = {'adi':'Mustafa','soyadi':'Kemal','eposta':'mustafa@mail.com'}
>>> doktorForm = DoktorFormu(gonderilenler)
>>> doktorForm.is_valid()
True
>>> gonderilenler = {'adi':'Mustafa','eposta':'mustafa@mail.com'}
>>> doktorForm = DoktorFormu(gonderilenler)
>>> doktorForm.is_valid()
False
İlk durumda form hatasız olduğu için True değeri döndürüldü. Fakat ikinci durumda soyadi kısmını zorunlu yapmıştık ve girilmediği için False döndü. Yani form hatalı bir şekilde doldurulmuş. Peki hatalı doldurulan kısımlar nereler? Bunu öğrenebilmek için , errors özelliğini kullanacağız.
>>> doktorForm.errors
{'soyadi': [u'This field is required.']}
Hataları buradan anladık. İngilizce olması önemli değil. Tarayıcıda, tarayıcının diline döndürülecektir.
Django formları kendi mekanizmasına göre denetler. Ama bazı durumlarda denetlemeyi kendi isteğimize göre değiştirmek isteyebiliriz. Bunun için clean_[alanadi]() fonksiyonunu kullanmamız gerekir. Django denetleme yaparken her form sınıfının altındaki bu işleve bakar. Şimdi telefon numarasının 11 karakterden oluşması için bu fonksiyonu yazalım.
class DoktorFormu(forms.Form):
 adi  =  forms.CharField(label="Adınız")
 soyadi  =  forms.CharField(label="Soyadınız")
 telefon =  forms.CharField(label = "Telefon Numaranız:",required=False)
 eposta  = forms.EmailField(label="E-Posta Adresiniz",required=False)

 def clean_telefon(self):
  tel = self.cleaned_data['telefon']
  if tel != "":
   if len(tel) != 11:
    raise forms.ValidationError('Telefon numarasi 11 karakter olmalidir.')
  return tel
Deneyelim.
>>> from yonetim.forms import *
>>> DoktorForm = DoktorFormu({'adi':'Mustafa','soyadi':'Metin','telefon':'5555'})
>>> DoktorForm.errors
{'telefon': [u'Telefon numarasi 11 karakter olmalidir.']}
Gördüğünüz gibi clean_[alanadi]() işlevini kullanarak kendi kontrolümüzü oluşturduk. Sizde istediğiniz bir alan için kontrol yapabilirsiniz.
Kaynakça