我现在用几个小时来尝试使用South进行最愚蠢的迁移,但不知何故,我一直在失败。我正在尝试迁移到Sorl-Thumbnail。
这是我的过渡模型:
class Deal(models.Model):
image = ImageWithThumbsField(upload_to='deal_images',null=True,blank=True,sizes=(200,150),))
new_image = ImageField(upload_to='new_deal_images',default='deal_images/thumb_deal_noimg.gif')
到目前为止,我的移民就是这样:
def forwards(self, orm):
for deal in orm.Deal.objects.all():
try:
image_name = deal.image.name.split('/')[1]
file_ = File(deal.image.open()) # I've also tried the method read()
deal.new_image.save('new_deal_images/'+image_name,file_,save=False)
except:
deal.new_image = None # For the default image kick in
deal.save()
这是此代码的最新版本。所有其他人,大多数都未能正确地将图像文件放在新目录中。
帮助......:)
时间流逝......
好吧......经过几次测试,我得到了这段代码:
def forwards(self, orm):
for deal in orm.Deal.objects.all():
file_content = ContentFile(deal.image.read())
deal.new_image.save(deal.image.name,file_content) *
deal.save()
正在复制图像并将其保存在新列(new_image)中,但问题是所有文件都保存在MEDIA_ROOT根目录中,而不是保存在所需的子目录('new_deal_images')中。我试过*行,但仍然没有运气:
deal.new_image.save('new_ideal_images/'+deal.image.name,file_content)
不能正常工作......
请帮助......:)
其他时间过去......
好吧......我认为南方有一些严重的问题:此代码在Django Shell中完美运行,将所有文件复制到正确的位置:
15 for deal in Deal.objects.all():
16 image_path = deal.image.path·
17 file_ = File(open(image_path,'rb'))
18 deal.new_image.save(deal.image.name,file_)
19 deal.save()
但是,迁移文件中的此代码不会转储MEDIA_ROOT根目录中的所有文件,而不会将其移动到正确的子目录中:
15 for deal in orm.Deal.objects.all():
16 image_path = deal.image.path·
17 file_ = File(open(image_path,'rb'))
18 deal.new_image.save(deal.image.name,file_)
19 deal.save()
答案 0 :(得分:4)
您可以在South orm中覆盖字段的generate_filename方法。例如,这会将“图像”字段中的所有图像复制到“new_image”字段,只需更改它们存储的目录。
for deal in orm.Deal.objects.all():
deal._meta.get_field('new_image').generate_filename = \
lambda inst, fn: os.path.join('new_deal_images', fn)
img_data = SimpleUploadedfile(deal.image.name, deal.image.read())
deal.image.close()
setattr(deal, 'new_image', img_data)
deal.save()
答案 1 :(得分:3)
我遇到了同样的问题,并通过直接分配路径而不是文件来解决这个问题:
for tagged in orm.ImageTag.objects.all():
with tagged.image.content:
filename = tagged.image.content.name.split('/')[1]
path = default_storage.save('taggedImages/' + filename, tagged.image.content)
tagged.imageFile = path
tagged.save()
答案 2 :(得分:1)
感谢Mike Fogel的回答,我在将图像从一个模型移动到另一个模型的迁移中解决了这个问题:
from south.v2 import DataMigration
from .. models import upload_by_conditions
from .. models import RESOURCE_IMAGE
class Migration(DataMigration):
def forwards(self, orm):
src = orm['uploader.Queue']
dst = orm['uploader.Resource']
for item in src.objects.all():
obj = dst(
kind=RESOURCE_IMAGE,
file_name=item.file_name,
file_type=item.file_type,
file_size=item.file_size,
)
# here I assign own handler!!!
obj._meta.get_field('resource').generate_filename = upload_by_conditions
obj.resource.save(item.file_name, item.image, save=True)
答案 3 :(得分:0)
虽然这可能不能直接回答你的问题,但我想我会在django south imageField migration主题中添加一些有用的洞察力(这个问题目前是网上最好的资源)。
South在数据迁移中处理图像字段的一个重要问题是,作为其ORM-Freezing的副作用,它似乎假设将使用DefaultStorage,因为存储不会被冻结。因此,如果您的现场有自定义存储空间,则可能无法按预期工作。但是@cberner提供了一些很好的见解,你可以直接利用存储直接保存和操作文件,然后只需设置字段的路径并保存它。撇开他的回答,我想出了以下数据迁移,将我现有的所有图像从一个存储(默认,文件系统存储)迁移到新存储(AWS):
这是从默认存储迁移到新存储(与将新存储添加到字段定义同时运行):
def forwards(self, orm):
new_images_storage = ImagesS3Storage()
for food in orm.Food.objects.all():
try:
new_file = ContentFile(food.image.read()) # south will use the default storage
new_file_path = new_images_storage.save(food_image_upload_to(food, food.image.name), new_file)
food.image = new_file_path
food.save()
except ValueError: # food with no image
continue
(作为参考,这是我的自定义存储,其存储桶与默认AWS存储桶不同,我的静态文件存储已使用该存储桶)
class ImagesS3Storage(S3BotoStorage):
def __init__(self, *args, **kwargs):
kwargs['bucket'] = getattr(settings, 'FOOD_IMAGES_BUCKET_NAME')
super(FoodImagesS3Storage, self).__init__(*args, **kwargs)
希望这会帮助一些失去的灵魂。