Normalde slugify fonksiyonu ile metni slug hale getirebiliyoruz. Ancak bu veritabanında bir kontrol yapmıyor elbette. Örneğin, kayıtları veritabanından URL'den gelen slug verisine göre çekecekseniz aynı başlıklı iki post olduğunda her zaman önce ilk ekleneni çekecektir.

Beyin Bedava

Söz konusu modelin save fonksiyonunu birazcık değiştirerek slug kontrolünü yapıp, benzersiz olana kadar sonuna sayı ekleyelim.

ornek-slug, ornek-slug-2, ornek-slug-3 gibi...

import itertools

from django.db import models
from django.utils.text import slugify

class Post(models.Model):
    title = models.CharField(max_length=128)
    slug = models.SlugField(editable=False)

    def save(self):
        if not self.pk:
            slug = slugify(self.title)

            for n in itertools.count(1):
                if not Post.objects.filter(slug=slug).exists():
                    self.slug = slug
                    break
                slug = '{}-{}'.format(slugify(self.title), n + 1);

        return super(Post, self).save()

İlk önce modelin pk (primary key) değeri olup olmadığını kontrol ediyoruz. Yani daha önce bu model (daha doğrusu nesne) veri tabanına eklenmiş mi (ki ID değeri ekleme esnasında oluşur) yani kullanıcı o an düzenleme mi yapıyor yoksa ilk defa mı eklenecek.

Ben slug belirleme işlemini sadece ilk defa eklenen kayıtlarda yapmayı uygun gördüm. Çünkü eğer kayıt yayınlandıktan bir süre sonra başlığı düzenlenirse yeni bir slug belirlenecektir ve kaydın linki değişecektir. Bu da hatalara (kayıt bulunamadı, 404 vs) sebep olabilir.

Bu kontrolü yapıp yapmamak size kalmış.

Önce kayıt başlığından normal bir slug belirledik. Ardından itertools ile birer birer artan bir döngü oluşturduk. Kaça kadar gittiğini bilmiyorum ama sonuna ulaşacağını sanmam.

Döngünün her adımında -geçici olarak belirlediğimiz- slug değerini veritabanında arayıp (exists) olup olmadığına baktık. Eğer böyle bir kayıt yoksa modelin slug alanını (self.slug) oluşturduğumuz slug yaptık ve döngüyü break ile sonlandırdık.

Eğer kayıt varsa slug değerini tekrar belirleyerek sonuna o anki döngü sayacını (+1 olarak) ekledik. Yani, eğer 3 aramadan sonra boş yer bulunursa slug değeri "cok-guzel-baslik-3" olacak.

Sayacı +1 olarak ekledik çünkü ilk aramadan sonra yer bulunduğunda (döngü sıfırdan başladığı için) slug değeri "guzel-baslik-1" oluyor. Karmaşaya yol açmasın diye en azından "guzel-baslik-2"den başlamasını sağladık.

If kontrolünün hemen altında, her halükarda üst sınıfın (django.db.models.Model) save fonksiyonunu çalıştırıp geriye döndürdük.

** Modelin slug alanında editable=False dedim çünkü manuel olarak belirlenememesini istedim. Dilerseniz kaldırabilirsiniz.

This post inspired by this. :P

Aynı sorunu yaşayıp aradığımda linkteki yazıyı buldum fakat çok fazla dolambaçlı olduğunu düşündüğüm için (ki belki raconu odur bilmiyorum) kendimce biraz kısalttım. Türkçe kaynak olsun diye de bu yazıyı yazdım.

Eyyorlamam bu kadar. Kolay gelsin...