29 Eylül 2008 Pazartesi

Django ile Anket 3

Bundan önceki uygulamarımızda anket oluşturmak, düzenlemek ve yeni seçenekler eklemek gibi bir takım ayarları yapmayı öğrenmiştik. Ama bunları sadece admin paneli üzerinden yapıyorduk. Peki bu anketleri nasıl sayfamızda gösterebiliriz ?

Anketleri sayfamızda gösterebilmemiz için anket uygulaması içerisinde yer alan view.py dosyasında bir takım düzenlemeler yapmamız gerekiyor. View.py dosyasının içeriğini şu hale getirelim.

from django.template import Context, loader
from OrnekProje.anket.models import Anket
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404

def index(request):
son_anketler = Anket.objects.all().order_by('-yayin_tarihi')[:5]
return render_to_response('anket/index.html',{'son_anketler':son_anketler })

def detail(request, anket_id):
p = get_object_or_404(Anket, pk=anket_id)
return render_to_response('anket/detail.html', {'anket': p})

def all(request):
anketler = Anket.objects.all().order_by('-yayin_tarihi')
return render_to_response('anket/all.html',{'anketler':anketler})

Ardından urls.py dosyanını şu şekilde düzenleyin. Bu arada yukarıda ki kodlar için acele etmeyin hepsini açıklayacağım ;)

urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),
(r'^anket/$', 'OrnekProje.anket.views.index'), #[1]
(r'^anket/(?P\d+)/$','OrnekProje.anket.views.detail'),
(r'^anket/all/$','OrnekProje.anket.views.all'),


Öncelikle urls.py dosyasından başlayalım. #[1] ile biten satıra bakalım. Bu satırda djangoya /anket/ adresine gelen bir istek olursa OrnekProje/anket/views dosyasından index fonksiyonun çalıştırılması isteniyor. ( url tanımı yapılırken kullanılan düzenli ifadelerden gökmen ve mirat daha önceki yazılarında bahsettikleri için uzun uzun değinmiyorum.) Şimdi gelelim index fonksiyonuna. İlk satırda son_anketler isimli değişkene veri tabanındaki son 5 anketi tarih sırasına göre atıyoruz. 2. satırda ise render_to_response nesnesini kullanarak
anket dizini içerisindeki index.html dosyanı son_anketler ile verilen değerleri kullanarak bir değer döndürmesini istiyoruz. (Sanki biraz karışık bir cümle oldu :/)

Ama sanki bir şey unuttuk ? anket/index.html diye bir dizin ve dosya yaratmadık. Şimdi OrnekProje dizini içerisinde Templates diye bir dizin oluşturalım. Burada tüm templatelerimizi saklayalım. İyi bir gruplandırma olması açısından her uygulama için ayrı bir dizin kullanalım. Yani onunda içerisinde bir anket dizini oluşturalım.

Bu dizinleri oluşturduktan sonra bunlardan djangoyu haberdar etmeye geldi sıra. Bunun için settings.py dosyasındaki TEMPLATE_DIRS satırını şu şekilde değiştirmemiz gerekiyor.

TEMPLATE_DIRS = ("/home/Deniz/OrnekProje/templates" # dizini kendi dizininizle değiştirmeri unutmayın :)
)


Şimdi tekrar templates/anket klasörüne gidip index.html dosyasını oluşturup içeriğini şu şekilde dolduralım.

{% if son_anketler %}
<ul>
{% for anket in son_anketler %}
<li>{{ anket.soru }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}



İlk satırda ki if sorgusu ile eğer son_anketler değeri var ise aşağıdaki işlemleri yapmasını söylüyoruz.

for döngüsü ise anket olduğu sürece anket sorularını ekrana bastırmamıza yarıyor.

Eğer if sorgusu False değeri döndürürse (yani hiç anket yoksa) else bloğu işletiliyor.

Burada sadece anket sorularını ekrana yazdırdık.

Şimdi urls.py dosyamızın 2. satırını ve detail fonksiyonunu açıklayalım. 2. satırda "/anket/2" "/anket/3" gibi sayfalara gelen isteklerde anket numarasına göre o anketi kullanmamızı için anket_id değerini parametre olarak detail fonksiyonuna gönderiyor.


def detail(request, anket_id):
p = get_object_or_404(Anket, pk=anket_id)
return render_to_response('anket/detail.html', {'anket': p})


Burda da farklı olarak get_object_or_404 nesnesini kullandık. Bu nesne eğer anket_id değeri ile gelen bir değer yoksa ekrana sayfa bulunamadı yazdırmamızı sağlıyor.

Bu da detail.html dosyamızın içeriği

<h1>{{ anket.soru }}</h1>
<ul>
{% for secim in anket.secim_set.all %}
<li>{{ secim.secenek }}</li>
{% endfor %}
</ul>


Burada 3 numaralı anketimizi görüntüledik.

Son fonksiyomuz olan all ve urls.py dosyasındaki ona ait olan satırı uzun uzun anlatmayacağım. Önceki bilgilerimiz ile neyin ne olduğunu anlayabiliriz :) Burada da tüm anketlerimizi ve şıklarını aynı anda sayfaya yazdırıyoruz.

all.html dosyasının içeriği;


{% for anket in anketler %}
<h3> {{anket.soru}} </h3>
{% for secim in anket.secim_set.all %}
<li> {{secim.secenek}} </li>
{% endfor %}
{% endfor %}




Yine template dosyaları aracılığıyla bu yazdıklarımızı özelleştirmek sizin elinizde ;)

25 Eylül 2008 Perşembe

Django ile Anket 2

Kaldığımız yerden devam edelim. Şimdi admin panelini kullanarak iki anket ekleyin.
Ben anket sorusu olarak "Hangi editörü kullanıyorsunuz ? " ve "Günde kaç saat bilgisayar başındasınız ?"'ı ekledim.
Ardından anasayfadan Anket bölümüne tekrar geldiğinizde eklediğimiz anketlerin listelendiğini göreceksiniz.

Sanırım hepiniz tuhaf giden birşeyler olduğunu fark etmişsinizdir. Tüm anketler "Anket object" ismiyle yani ne olduğunu anlayamadığımız bir isimle listelenmekte. Gelin bunu rahat anlaşılabilir bir hale nasıl sokabiliriz onu inceleyelim.

Bunun için models.py dosyamızdaki sınıflarımızın altına şu satırları ekliyoruz.

def __unicode__(self):
return self.soru


Bunu anket sınıfının altına ekliyoruz. Burada verdiğimiz self.soru veritabanında ki kaydımızın ismi.


def __unicode__(self):
return self.secim

Bunu da Secim sınıfına ekliyoruz.

Şimdi admin panelini güncelleyip nasıl göründüğüne bir bakalım. Sanırım bu hali daha açıklayıcı olmuştur ;)

Şimdi de alanların yerlerini değiştirelim. Şu anda bir anket eklerken ilk sırada soru 2. sırada da yayin tarihi bulunuyor. Şimdi bunların yerlerini değiştirelim. Anket dizini içerisindeki admin.py dosyasında admin.site.register() yerine aşağıdaki satırları ekleyin.

class AnketAdmin(admin.ModelAdmin):
fields = ['yayin_tarihi','soru']

admin.site.register(Anket,AnketAdmin)

Değiştirdikte ne oldu yani şimdi ? dediğinizi duyar gibi oluyorum :) Anket uygulaması gibi 2 alandan oluşan bir uygulamada pek bir işe yaramaz ama alan sayısı arttıkça sıralamanın istediğini gibi olmasını isteyebilirsiniz. Ya da sık kullanılmayan bazı alanları gizlemek ya da benzer kategorileri gruplandırmak. Şimdi bunlara da birer örnek verelim. İhtiyacınız olduğunda bu da varmış diye aklınızda bulunsun ;) Yine admin.py dosyasında ki AnketAdmin clasını değiştiriyoruz.

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi']}),
]

Bu değişiklikle Yayin Tarihi bilgileri ayrı bir bölümde Tarih Bilgileri başlığıyla gösterilecek. Tarayıcımıza gidip hemen bir kontrol edelim.

Ardından da ufak bir değişiklik daha yapalım.

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi'],'classes': ['collapse']}),
]


Neyse bu kadar ince ayar yeter. Biz anketimize geri dönelim. Anketi hazırladık fakat sorular yok. Hemen sorularıda admin paneline tanıtalım. Bunun nasıl yapıldığını daha önce görmüştük. admin.py dosyasını açıyoruz tekrar.

admin.site.register(Secim)

Satırını ekliyoruz.

Ardından Secimleri seçip bir kaç seçenek ekleyelim ki anketimiz şenlensin ;)
Yeni seçenek eklerken yukarıdan hangi ankete ekleyeceğimiz seçiyoruz. Fakat önce soruyu ekle sonra seçenekleri ekle falan bana pek kullanışlı gelmiyor. Eğer sizde benim gibi düşünüyorsanız birde şunu deneyin.

Az önce eklediğimiz satırı kaldırıp AnketAdmin sınıfının sonuna inlines = [Secimler] i ekliyoruz. Yani dosyamızın son hali şuna benzeyecek.

from OrnekProje.anket.models import Anket
from OrnekProje.anket.models import Secim
from django.contrib import admin


class Secimler(admin.StackedInline):
model = Secim
extra = 4

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi'],'classes': ['collapse']}),
]
inlines = [Secimler]

admin.site.register(Anket,AnketAdmin)

Yeniden bir kayıt girmeyi deneyin ya da girdiğiniz kayıtları düzenleyin.
Birde Secimler(admin.StackedInline) yerine admin.TabularInline şeklinde kaydedip deneyin. Hangisi daha hoş ?

Ekleme bölümünü baya bir kurcaladık. Sıra geldi değişiklik bölümüne, Anketler-Değiştire geldiğinizde sadece anketin ismini görebiliyorsunuz. Şimdi biraz daha ayrıntı ekleyelim. inlines seçeneğinde yaptığımız gibi bir değişiklik yapacağız. admin.py dosyasında AnketAdmin sınıfı altına şu satırı ekleyelim.

list_display = ('soru','yayin_tarihi')

Şimdi sayfamızı yenileyelim. Ardından az önceki örnekte olduğu gibi aşağıdaki satırlarıda tek tek(!) ekleyerek her birinin neler yaptığını anlamaya çalışın.

list_filter = ['yayin_tarihi']
search_fields= ['soru']
date_hierarchy = 'yayin_tarihi'

23 Eylül 2008 Salı

Django ile Anket

Bu uygulamamızın temel amacı django ile admin panelini anlatmak olacak. O yüzden onun dışında kalan bölümleri hızlıca geçeceğim.O bölümler daha önce gökmen ve mirat tarafından ayrıntılı olarak anlatılmıştı. Eğer başlangıçtaki bazı örnekleri anlayamazsanız daha önce yazılmış django notlarından faydalanabilirsiniz.

Şimdi yeni bir proje başlatmak için gerekli olan komutumuzu veriyoruz.

Deniz@ParMak ~ $ django-admin.py startproject OrnekProje

OrnekProje adıyla yeni bir projeye başladık şimdi o dizine geçip uygulamamıza devam edelim.

Deniz@ParMak ~ $ cd OrnekProje/


Şimdi de projemiz içerisinde yeni bir uygulama başlatalım.
Not: Uygulamalar genellikle belirlir bir görevi yerine getirmek üzere kullanılırken. Projeyi ise içinde bir çok uygulamayı içerisinde düzenli şekilde barındıran uygulamalar bütünü olarak tanımlayabiliriz. Yine uygulamalarımızı bir kere oluşturup farklı projeler içerisinde de kullabiliriz.

Deniz@ParMak OrnekProje $ python manage.py startapp anket

Projemiz içerisinde anket isimli bir dizin oluştuğunu göreceksiniz içinde ise "__init__.py __init__.pyo models.py models.pyo views.py views.pyo " dosyaları mevcuttur.

models.py dosyası bizim modellerimizi tanımlayacağımız dosya olacak. Anket uygulaması için 2 model oluşturacağız: Anket ve Secim. Anket içerisinde soru ve yayın tarihi yer alırken Secim içerisinde secenekler ve oylar alanları yer alacak. Bunun için aşağıda ki kodları models.py dosyamıza kaydediyoruz.

from django.db import models

class Anket(models.Model):
soru = models.CharField(max_length=200)
yayin_tarihi = models.DateTimeField('yayin tarihi')

class Secim(models.Model):
anket = models.ForeignKey(Anket)
secenek = models.CharField(max_length=200)
oylar = models.IntegerField()


Şimdide bir üst dizinde yer alan settings.py dosyasında INSTALLED_APPS kısmını şu şekilde düzenliyoruz.


INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'OrnekProje.anket',
)


Şimdi veri tabanı ayarlarını düzenliyoruz. (Ayrıntılı bilgi için miratın yazını inceleyiniz.


DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'veritabanı_ismi' # Or path to database file if using sqlite3.
DATABASE_USER = 'Deniz' # Not used with sqlite3.
DATABASE_PASSWORD = 'şifrem' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.

Eğer Pardus kullanıyorsanız Tasma-Servis Yöneticisinden mysql_server'i çalıştırmayı unutmayınız.

Ardından bakalım az önce models.py içerisine pythoncasını yazdığımız modellerin mysql karşılıkları nelermiş ?

Deniz@ParMak OrnekProje $ python manage.py sql anket
BEGIN;
CREATE TABLE `anket_anket` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`soru` varchar(200) NOT NULL,
`yayin_tarihi` datetime NOT NULL
)
;
CREATE TABLE `anket_secim` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`anket_id` integer NOT NULL,
`secenek` varchar(200) NOT NULL,
`oylar` integer NOT NULL
)
;
ALTER TABLE `anket_secim` ADD CONSTRAINT anket_id_refs_id_4e3e5fcb FOREIGN KEY (`anket_id`) REFERENCES `anket_anket` (`id`);
COMMIT;


Eğer benzer bir çıktı aldıysanız herşey yolunda devam edebiliriz.
Eğer bir hata almadıysanız djangoya az önceki sql komutlarını çalıştırmasını söylemek için aşağıda ki komutu giriyoruz.

python manage.py syncdb

Çıktısında şöyle birşey göreceksiniz.

Creating table anket_anket
Creating table anket_secim
Installing index for anket.Secim model

Şu ana kadar veri tabanı ayarlarımız yaptık şimdi Admin paneliyle ilgili ayarlarımıza geçiyorum.

Tekrar setting.py dosyasını açıp INSTALLED_APPS bölümüne az önceki örnekteki gibi 'django.contrib.admin' satırını ekliyoruz.

Ardından tekrar python "manage.py syncdb" komutunu verip veri tabanını güncellemesini istiyoruz. Bu esnada sizden admin paneline girişte kullanmanız için bir kullanıcı adı ve şifresi isteyecek gerekli ayarları yapıp devam ediniz.

Son olarakta urls.py dosyasının başında admin paneli için gerekli olan modülleri yüklemek için # işaretini kaldırıyoruz. Ve yine o dosyanın sonundaki admin alanını djangoya göstermek için oradan da # işaretini kaldırıyoruz.
Yani dosyanın en son hali şu şekilde olacak.

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
# Example:
# (r'^OrnekProje/', include('OrnekProje.foo.urls')),

# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),

# Uncomment the next line to enable the admin:
(r'^admin/(.*)', admin.site.root), #burasını
)

Şimdi django sunucusunu çalıştıralım.

python manage.py runserver

Şimdi tarayıcınızdan http://127.0.0.1:8000/admin/ adresini açıp neler olduğuna bakabilirsiniz :)

Biraz kurcalayınca Gruplar,Kullanıcılar ve Siteler adında 3 bölüm göreceksiniz. Bunlar django ile öntanımlı olarak gelen admin paneli araçlarıdır. Fakat sanki bizim anket piyasada görünmüyor ? Bunun için yapmamız gereken tek birşey daha kaldı. Anket dizini içerisine admin.py adında bir dosya oluşturup içerisine şu satırları eklemek.

from OrnekProje.anket.models import Anket
from django.contrib import admin

admin.site.register(Anket)


Şimdi sunucumuzu yeniden başlatalım.(Ctrl+c) ile sonlandırıp. python manage.py runserver ile yeniden başlatabilirsiniz.

Eğer bir aksilik çıkmadıysa artık admin panelinde anket uygulamımızı görmüşsünüzdür. Aslında buradan sonra anlatılacak pek birşey kalmıyor ama ben kısaca bir kaç ufak şeyden bahsedeyim.

*Anketlere girdiğimizde görmüş olduğumuz form anket modelinde yazmış olduğumuz koda göre django tarafından otomatik olarak oluşturuluyor.

*Anket modelinde oluşturduğumuz alanları hatırlayacak olursanız (DateTimeField, CharField gibi) django bunlara bakarak admin panelinde ona göre bir html üretiyor.

*Örneğin DateTimeField ile gün ayarı yapabileceğimiz bir JavaScript kısayolunu bizim için panele ekliyor.

Şimdilik bu kadarla kesiyorum. Admin panelinide kendi isteğimize göre özelleştirebiliyoruz. İlerleyen günlerde bu ufak tefek özelleştirmelerden de bahsedebilirim.