为什么upload_to
值会更改photo.name
的值?我正在尝试在运行时创建一个专辑目录,并在相应的专辑目录中编辑我的图像。我的代码能够使用相应的相册名称创建一个目录,并在其中包含正确的照片,但它会将self.photo.name
更改为upload_to
值。
在下图中。使用管理界面,我创建了一个名为test4
的相册,我选择上传tumblr_nh09woLkmb1sfie3io1_1289.jpg
。 self.photo.name
的值为test4/tumblr_nh09woLkmb1sfie3io1_1289.jpg
。
在我的upload_path
方法中,我也尝试了
return instance.album.title
return '/' + instance.album.title
return instance.album.title + '/'
这不会创建名称为instance.album.title
的目录,而是在我的MEDIA_ROOT
文件中保存upload_path
方法返回的名称。不是实际的文件名。
我觉得预期的self.photo.name应该是上传照片的名称。在这种情况下tumblr_nh09woLkmb1sfie3io1_1289.jpg
from django.db import models
from django.contrib import admin
from PIL import Image
from django.conf import settings
import os.path
from django.utils.html import format_html
from django.core.files.storage import FileSystemStorage
import re
class Album(models.Model):
title = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.title
def images(self):
lst = [x.photo for x in self.photo_set.all()]
return lst
def save(self, *args, **kwargs):
# super(Album, self).save(*args, **kwargs)
rgx = re.search(r'.*\w', self.title)
self.title = rgx.group(0).replace(" ", "_")
super(Album, self).save(*args, **kwargs)
class AlbumAdmin(admin.ModelAdmin):
search_fields = ["title"]
list_display = ["images"]
def upload_path(instance, filename):
if " " in instance.album.title:
instance.album.title.replace(" ", "_")
return '/'.join([instance.album.title, filename])
class Photo(models.Model):
title = models.CharField(max_length=50, blank=True)
album = models.ForeignKey(Album)
photo = models.ImageField(upload_to=upload_path)
upload = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def size(self):
return "%s x %s" % (self.photo.width, self.photo.height)
def thumbnail(self):
thumbnail_html = "<a href=\"{0}{1}\"><img border=\"0\" alt=\"\" src=\"{2}{3}\" height=\"40\" /></a>".format(settings.MEDIA_URL, self.photo.name, settings.MEDIA_URL, self.photo.name)
print settings.MEDIA_URL, settings.MEDIA_ROOT
return thumbnail_html
thumbnail.allow_tags = True
class PhotoAdmin(admin.ModelAdmin):
search_fields = ["title", "photo"]
list_display = ["photo", "thumbnail", "title", "album", "size"]
list_filter = ["album"]
答案 0 :(得分:1)
关于upload_to
函数的Django文档(https://docs.djangoproject.com/en/1.7/ref/models/fields/#django.db.models.FileField.upload_to)。
将附加到MEDIA_ROOT设置的本地文件系统路径,以确定url属性的值。
因此,如果您将upload_to
指定为函数,Django将尝试将文件名保存为MEDIA_ROOT
的相对路径。
答案 1 :(得分:1)
您有以下设置:
MEDIA_ROOT = os.path.join(BASE_DIR, "../media_root/Boothie/pics")
MEDIA_URL = '/media/'
因此,每当您将upload_to
传递给FileField
或ImageField
路径或函数时,它将以string_passed_to_upload_to/filename.ext
格式保存在数据库中或由传递给它的函数。这样就可以重新创建文件的完整路径:MEDIA_ROOT + instance.photo.name
和url:MEDIA_URL + instance.photo.name
。这不是django的确切代码,只是为了给你一个想法。是否有意义?我可以通过一些例子详细说明。
修改强>
如果您希望只能获得基本文件名,可以执行os.path.split(photo.name)[1]
。但无论如何,FileField都会将文件名存储在与MEDIA_ROOT
路径相关的数据库中。
您还可以结帐django-smartfields应用,它具有该属性设置,因此如果您有型号:
from smartfields import fields
def upload_path(instance, filename):
if " " in instance.album.title:
instance.album.title.replace(" ", "_")
return '/'.join([instance.album.title, filename])
class Photo(models.Model):
title = models.CharField(max_length=50, blank=True)
album = models.ForeignKey(Album)
photo = fields.ImageField(upload_to=upload_path, keep_orphans=True)
upload = models.DateTimeField(auto_now_add=True)
你可以这样使用它:photo.photo.name_base
。确保您转到字段keep_orphans=True
,否则它将删除旧文件。
答案 2 :(得分:1)
这可能对您有所帮助,在此示例中使用os.path.basename(self.file.name)而不是file.name。
class FileModel(models.Model):
file = models.FileField(upload_to="images/")
def __unicode__(self):
return str(os.path.basename(self.file.name))
@property
def filename(self):
return str(os.path.basename(self.file.name))
在模板文件中使用file.url
答案 3 :(得分:1)
class Photo(models.Model):
def upload_path(self, name):
return '{0}/{1}'.format(
self.album.title,
name.lower().replace(' ', '_').encode('trans')
)
photo = models.ImageField(upload_to=upload_path)
因此,如果您将upload_to定义为类方法,则可以按相关对象的字段&#39; title&#39;进行操作,例如将其作为子目录包含在图像路径中。