Django’da modeller nasıl oluşturuluyor?

Django’da örneğin şöyle bir modelim var:

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

Bu sınıftan p1 = Publisher(…) şeklinde onlarca instance oluşturabiliyorum, fakat işin garip yanı, tüm instanceların özellikleri(attribute) farklı olabiliyor, halbuki böyle olması için bu kodun şu şekilde olması gerekmez miydi?

class Publisher(models.Model):
    def __init__(self):
        self.name = models.CharField(..)
        vs vs vs..

Bu nasıl olabiliyor ve kendi sınıflarıma nasıl uygulayabilirim? Araştırıyorum..

Python ile altyazı işlemleri 2

Daha önceden Python’da regex kullanarak altyazılar üzerinde bazı değişiklikler yapmıştım(ilk yazı burda). Bu seferki kod altyazılar srt formatlı altyazılar için birkaç fonksiyon içeriyor.

"""
subtools.py
Some subtitle tools for .srt formatted subtitles.
"""
import re

def convert(a):
    parts = a.split(":")
    hour, minute, sec = int(parts[0]), int(parts[1]), parts[2]
    minute += hour*60
    sec = sec.split(",")
    sec = int(sec[0])*1000 + int(sec[1])
    sec += minute*60000
    return sec

def revert(a):
    a = int(a)
    sec, remainder = a/1000, a % 1000
    minute = sec/60
    sec = sec%60
    hour = minute/60
    minute = minute%60
    # kod tekrarini nasil engelleyebilirim?
    if len(str(hour)) == 1:
        hour = "0%s" % hour
    if len(str(minute)) == 1:
        minute = "0%s" % minute
    if len(str(sec)) == 1:
        sec = "0%s" % sec
    if len(str(remainder)) == 1:
        remainder = "00%s" % remainder
    elif len(str(remainder)) == 2:
        remainder = "0%s" % remainder
    return "{0}:{1}:{2},{3}".format(hour, minute, sec, remainder)

def adder(a, b):
    return revert(convert(a) + convert(b))

def subtracter(a, b):
    return revert(convert(a) - convert(b)))

def submod(sub, time):
    "Advance subtitles"
    Sub = open(sub, "r").readlines()
    format = re.compile(r"(\d{1,2}:\d{1,2}:\d{1,2},\d{1,3}) --> (\d{1,2}:\d{1,2}:\d{1,2},\d{1,3})")
    for line in Sub:
        if format.findall(line):
            parts = format.findall(line)
            parts = parts[0]
            P1, P2 = adder(parts[0], time), \
                           adder(parts[1], time)
            Sub[Sub.index(line)] = "%s --> %s" % (P1, P2)
    new = open("new_%s" % sub.split("/")[-1], "w")
    new.writelines(Sub)
    new.close()

def setsub(sub, first, last):
    submod(sub, subtracter(first, last))

Linux ortamında VLC ile birşeyler izlerken en çok sıkıntı çektiğim konu GOM Player’daki altyazının istenilen kısmının filmdeki istenilen zamana denk getirilme özelliğinin olmaması, bu fonksiyonlar kullanılarak kolayca yapılabilir aslında..

Python’da recursion: dosya ağacı?!

Recursion kullanarak yapılabileceklere bir örnek, bir arkadaşa göstermek için yazdığım bir dosya ağacı(böyle birşeydi adı) scripti.

#kullanım: örn. treeGen("/home/osa1/")
import os

def treeGen(place, x=0, sub="-"*6):
    main = os.listdir(place)
    for file in main:
        if os.path.isdir(place + file):
            print("%s[%s]" % (sub * x, file), end="\n")
            treeGen(place + file + "/", x+1)
        else: print("%s%s" % (sub * x, file))

Ayrıca http://wiki.python.org/moin/SimplePrograms adresinden küçük programcıklar bulabilirsiniz.

Python ile Linux ortamında DNS değiştirme

Tek tıkla kullandığınız DNS’i Google ya da openDNS’e ayarlayan bir program yazmak çok kolay aslında. Linux ortamında(ve sanırım tüm UNIX ailesinde) o an için kullandığınız DNS adresleri /etc/resolv.conf dosyasında, “# Generated by NetworkManager” satırının altında tutuluyor. Kısaca orayı değiştirerek yapıyoruz.

Gayet basit bir şekilde open fonksiyonu ile dosyayı “w” modunda açıp, içine DNSleri yazdırıyoruz, bu arada eğer ağı kopartıp bir daha bağlanmamız gerekirse, komutlarımız “ifconfig ağ_adı down/up”. Bunu terminalden yazmak gerekiyor ama os.system kütüphanesini kullanarak bu işi programımıza yaptırabiliriz.

Kısaca şöyle oluyor:

import os.system

DNS = {
    "google" : ["8.8.8.8", "8.8.4.4"]
    "opendns" : [] #buraya opendns ekle
    }

open("etc/resolv.conf", "w")
open.writelines(DNS["google"]) #ya da opendns
open.close()

#bağlantıyı koparmak
os.system("ifconfig ag_adi down")
#yeniden bağlanmak
os.system("ifconfig ag_adı up")

Python ile eğlenmek ve PyCon

Dün gece yorgun bir şekilde Python çalışmalarıma devam ederken, öğrendeğim birkaç şey “puhahahs” şeklinde kahkahalar atmama sebep oldu(biraz da uykusuzluğun etkisiyle). Örneğin şu koda bakalım:

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17

Bu kod bu çıktıyı verince nedense komik geldi ve saçmalamaya başladım(bu arada sonuç 0′a çok yakınmış, ben hesaplamadım), neyse ki kitap hemen altında sebebini ve nasıl düzeltileceğini anlatıyor(Learning Python, O’Reilly, şu ana kadar gördüğüm en güzel Python kaynağı). Çözümü için decimal kütüphanesini inceleyebilirsiniz.

Neyse, biraz dinlendim, kitabı yeniden elime aldım ve ilerlemeye devam ettim, derken bir şey daha beni kopardı; Python’da True ve False’un aslında 1 ve 0′ı ifade ettiğini biliyoruz, fakat bu kadarı da fazla:

>>> True + 4
5

:) Neyse ki durum sandığım kadar abartı değilmiş:

>>> True is 1
False

Bu arada, Python’a veya hem Python’a hem programlamaya yeni başlayanlara Learning Python kitabını kesinlikle tavsiye ediyorum. Şu ana kadar bir sürü kitap -tüm türkçe kaynaklar, en yetersizleri bunlar zaten, Beginning Python: From Novice to Professional, Python Programming for Absolute Beginner, Invite with Python, Deitel’ın meşhur serisini Python versionu olan Python How to Program ve okulumun kütüphanesinden adını hatırlayamadığım birkaç Python kitabı- okudum/inceledim ve bu kadar yeterli, işin temelini ve arkaplanını anlatan bir kitap daha görmedim. Biraz kalındır, ama hakkıyla öğrenirsiniz diye düşünüyorum. Ben artık bir sürü kaynaktan okuduktan sonra çok iyi bildiğimi düşündüğüm konularda(sayılar, stringler..) bilmediğim ne kadar çok şey olduğunu farkettim.

Bir yandan da yeni birşeyler öğrenmek için PyCon videolarını tavsiye ediyorum. Çok çeşitli konularda çok ilginç kullanımlar görebilirsiniz. 2010′daki PyCon’da Guido’nun konuşmasını güzelmiş mesela :)

Bsod arşiv düzenleyici

İlk işe yarar Python programımı tamamladım, bir sürü gerekli gereksiz problemler çözdüm Python’da fakat bu seferki gerçekten bir ihtiyacımı karşıladı.

Bsod arşiv düzenleyici; birkaç kb büyüklüğünde mp3, ogg ve flac formatlarından oluşan müzik arşivinizi başka bir klasöre artist adı/albüm/şarkı adı şeklinde taşımaktadır. Bu formatlara uymayan diğer dosyalar da _OTHERS klasörüne kopyalanmaktadır. Bir arayüzü olmadığından ekran görüntüsü koyamıyorum.

Program hakkında bazı notlar:

  • Tek bağımlılığı Python2.6 veya daha üst bir Python2.x sürümüdür. Aslında bir de Mutagen kütüphanelerine ihtiyaç duyuyor fakat zaten birkaç kb olduklarından ben onları paketin içine attım.
  • Tüm arşivi kopyalayacaktır, formatları desteklemese yada müzik dosyalarının etiketleri olmasa bile _OTHERS klasörüne kopyalanacaklar, herhangi bir kayıp olmayacak yani.
  • Eski arşivinizde kesinlikle değişiklik yapılmayacaktır.
  • Ogg formatında ve Windows ortamında test edilememiştir. Fakat kaynak koda bakıldığında bir sorun çıkmayacakmış gibi geldi bana. Test edip yorum yaparsanız menun olurum :) .
  • Arayüzü olmadığından terminal veya komut satırından çalıştırmanız gerekiyor.

Eğer geliştirebilirsem ileriki versionlarda albüm kapağı ve şarkı sözleri indirme özellikleri ekleyebilirim. Fakat önce bunları indirebileceğim sunuculara ihtiyacım var(Media Player falan nereden indiriyor bir çözübilsem :P). Etiket düzenleyicisi de eklenebilir kolayca, ama amacımın dışına çıkmış olurum.

Bu arada unutmadan, buradan indirebilirsiniz.

EKLEME: Windows ortamında çalışmadığı haberlerini aldıktan sonra birkaç değişiklik yaptım. Kendi kopyala/yapıştır fonksiyonum yerine shutil kütüphanesini, kopyalayacağım dosyanın varlığını kontrol etmek için os.path kütüphanesini kullandım, bağlantıları kurarken elle “/” koymak yerine os.sep kullandım, ve sanırım bu sefer, Windows ortamında da sorunsuz çalışacaktır :) . Denendi; Windows ortamında çalışıyor.

Python’da recursion

Bilgisayar Bilimcisi Gibi Düşünmek‘i okuduktan sonra recursion ve recursive fonksiyonlar diye birşeyle tanıştım, aslında garip falan değiller fakat öğrenmesi ve nasıl çalıştıklarını anlaması biraz zor(ya da bana öyle geldi). Uzun süredir yapma planları kurduğum MP3 arşiv düzenleyicimi yapmak için kullanmam gerekti(klasörleri en alt klasöre kadar taramak için).

Recursive fonksyionları “özyinelemeli” fonksiyon diye tercüme etmişler, kısaca kendini çağıran fonksiyonlar diyebiliriz. Daha detaylı bilgi için Wikipedia. En basit örnekleri faktoriyel ve fibonacci fonksiyonları. Alternatif çözümleri tabii ki vardır, bunlar recursion kullanarak çözümlerim:

def recursive_faktoriyel(x):
    if x == 1:
        return 1
    return x * recursive_faktoriyel(x-1)

def recursive_fib(n):
    if n == 1: return 0
    if n == 2: return 1
    return fib(n-1) + fib(n-2)

Kitapta alternatif çözümler vardı(sanırım). Kitabı tavsiye ediyorum bu arada, özellikle recursion ve sözlüklerle alakalı bölümlerde çok güzel teknikler öğrendim, birde GASP modülünden haberim oldu(bir işime yaramayacak gerçi, Ubuntu’da paket yöneticisinden kurulabiliyor).

Benim programımda recursion’ı kullanma amacım ise içiçe geçmiş listeleri ayırmaktı, örneğin elimde şöyle bir liste var:

  1. [1, 2, 3, [4, 5, [6, [7, [8], 9]]], 10, 11]

Bu listeyi ayırmak için bir sürü farklı fonksiyon yazabilirsiniz, benim çözümüm şu oldu:

seq2 = []
def recursive(seq):
    for element in seq:
        if type(element) == type([]):
            recursive(element)
        else:
            seq2.append(element)
    return seq2

Kod gayet güzel çalışıyor fakat eğer daha “recursive” olarak yazmak isterseniz, internetten bulduğum şu kodu kullanabilirsiniz:

def recursive2(seq):
    if not isinstance(seq, list):
        return [seq]
    elif seq == []:
        return []
    else:
        return bill_recursive2(seq[0]) + bill_recursive2(seq[1:])