Django - Benzersiz Slug Alanları Oluşturma
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.
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...