products/models.py
class Product(models.Model):
type = models.PositiveSmallIntegerField(choices = PRODUCT_TYPES,)
category = models.ForeignKey(Category)
name = models.CharField(max_length=50)
slug = models.SlugField()
image = models.ImageField(upload_to = "product_images")
def __unicode__(self):
return self.name
Yapmak istediğim ise şu : yönetici panelinde bu modeli kaydederken verilen dosyanın soyadı değişmeden isminin slugfield olarak değiştirilip kaydedilmesi.
Örnek vermek gerekirse adı "Vestel Cep Televizyonu" olan bir ürünü image alanı img13.jpg dosyası ile kaydettiğimi düşünelim. Bu durumda image, "product_images/vestel-cep-televizyonu.jpg" olarak kaydedilmeli (soyadı olan jpg aynı kalıyor, dosyanın adı slug ile eşitleniyor)
Bunu yapabilmek için düşünmeye başladığımda admin site'sinin, save_model fonksiyonunu override edebildiğimizi öğrendim ve şöyle bir şey yazdım :
from os.path import dirname, join, splitext
from shutil import move as rename
class ProductAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("name",)}
def save_model(self, request, obj, form, change):
extension = splitext(obj.image.path)
new_image_path = join(dirname(obj.image.path), obj.slug + extension)
rename(obj.image.path, new_image_path)
obj.image.path = new_image_path
obj.save()
Fakat bu şöyle bir hataya yol açıyordu :
File "/home/horselogy/django/mobil8/../mobil8/products/admin.py" in save_model
36. obj.image.path = new_image_path
Exception Type: AttributeError at /admin/products/product/2/
Exception Value: can't set attribute
Saatlerce path değişkenini set edemiyorum diye saç baş yolduktan sonra fark ettim ki tek yapmam gereken obj.image = "uploaded/path" şeklinde yolu göstermem. Çünkü name ve path değerleri bu şekilde otomatik olarak set ediliyor. Neyse son hali ile şu şekilde olayı gerçekleştirdim
products/admin.py
class ProductAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("name",)}
def save_model(self, request, obj, form, change):
extension = splitext(obj.image.path)[-1]
new_image_name = obj.slug + extension
new_path = join(dirname(obj.image.path), new_image_name)
rename(obj.image.path,new_path)
obj.image = join("product_images", new_image_name)
obj.save()
Bir dili anlarken çok zor bir dönem geçer, en aptal şey için bile saatlerinizi harcarsınız. Sonrası çorap söküğü gibi gelir her şey kolaylaşır. Sanırım bende Django konusunda bu dönemden geçiyorum. Sizin dönemlerinizin sancısız olmasını diliyor yazıyı burada bitiriyorum :).
obj.image = join("product_images", new_image_name) bu satırda el alışkanlığından join kullanmışım :) burada verilen yol dosya yolu değil url yolu o yüzden "product_images/" + new_image_name şeklinde kullanmalıydım.
YanıtlaSilSelam,
YanıtlaSilupload_to member member'inin degerini string yerine fonksiyon olarak yazilirsa django dosyayi kaydetmeden once bu dosya yolunu bu fonksiyona soruyor.soyle;
====
class Image(Model):
file = ImageField(upload_to=get_image_path)
====
# yeni image instance i yaratildiginda, dosya tam kaydetilecekken bu fonksiyon instance objesi ve filename stringiyle cagrilacak
def get_image_path(instance,filename):
.....
return "%s%s"%(instance.pk,extension)
===
azer
mazeretim var o yüzden mazur görün "slug" tabirini kullanmışsın bu tam olarak neye karşıt geliyor neyi anlatıyor?
YanıtlaSilherhangi bir şey mi demek yoksa - işaretiyle ayrı yazılmış kelimeleremi deniyor?
Bazı yerlerde yine karşıma çıktı öyle baka kaldım :D
Django dökümantasyonunda slug'tan şöyle bahsediliyor.
YanıtlaSilhttp://docs.djangoproject.com/en/dev/glossary/#term-slug
@Azer : Bahsi geçen, file upload'larının dinamik olarak yapılması olayı henüz yapılmamış.
YanıtlaSilhttp://code.djangoproject.com/ticket/4113 adresinde bu konu "Design decision needed" konumunda bekliyor. Atladığım (ya da atladığın) bir şey mi var?