В процессе переработки HTML5 аплоадера картинок пришлось поменять структуру хранения в БД. Из-за необходимости плавного переезда системы на новый функционал был выбран путь через создание другой модели.
Вот как выглядит новая модель:
# models.py
def upload_by_conditions(instance, filename):
u"""Возвращает путь для загружаемого файла, учитывая его тип и назначение."""
return u'uploader/media/%s/%s' % (instance.uploaded_for.code, filename)
RESOURCE_UNKNOWN = 0
RESOURCE_IMAGE = 1
RESOURCE_LAYOUT = 2
RESOURCE_CHOICES = (
(RESOURCE_UNKNOWN, _(u'Unknown')),
(RESOURCE_IMAGE, _(u'Image')),
(RESOURCE_LAYOUT, _(u'Layout')),
)
MIMETYPE_IMAGES = ('image/jpeg', 'image/png', )
MIMETYPE_LAYOUTS = ('image/gif', )
class Resource(models.Model):
kind = models.PositiveIntegerField(choices=RESOURCE_CHOICES, default=RESOURCE_UNKNOWN, verbose_name=_(u'Type'))
resource = models.FileField(upload_to=upload_by_conditions, max_length=256, verbose_name=_(u'Resource'))
file_name = models.CharField(max_length=256, verbose_name=pgettext_lazy(u'uploader', u'Name'))
file_type = models.CharField(max_length=80, verbose_name=_(u'MIME'))
file_size = models.PositiveIntegerField(default=0, verbose_name=pgettext_lazy(u'uploader', u'Size'))
position = models.PositiveIntegerField(default=0, verbose_name=_(u'Position'))
is_visible = models.BooleanField(default=False, verbose_name=_(u'Visible for anonymous'))
is_staff = models.BooleanField(default=False, verbose_name=_(u'Visible for staff'))
is_teaser = models.BooleanField(default=False, verbose_name=_(u'Used for presentation'))
uploaded_for = models.ForeignKey('storage.Project', related_name=u'resource', verbose_name=pgettext_lazy(u'uploader', u'Uploaded For'))
uploaded_by = models.ForeignKey('auth.User', related_name=u'uploaded_by', verbose_name=pgettext_lazy(u'uploader', u'Uploaded By'))
uploaded_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-uploaded_at', )
verbose_name = _(u'Resource')
verbose_name_plural = _(u'Resources')
Как видно, путь до каталога в котором будет сохранятся изображение вычисляется по идентификатору (не PK) проекта.
Миграция сделана просто -- читаем содержимое оригинальной модели и сохраняем его в новую модель.
# migration.py
class Migration(DataMigration):
def forwards(self, orm):
src = orm['uploader.Queue']
dst = orm['uploader.Resource']
model = orm['storage.Project']
for item in src.objects.all():
project = model.objects.get(code=item.tags)
obj = dst(
kind=RESOURCE_IMAGE,
file_name=item.file_name,
file_type=item.file_type,
file_size=item.file_size,
position=item.position,
is_visible=item.visible,
is_staff=item.staff,
is_teaser=item.teaser,
uploaded_for=project,
uploaded_by=item.uploaded_by,
uploaded_at=item.registered
)
obj.resource.save(item.file_name, item.image, save=True)
Всё работает нормально, кроме одного. Изображения сохраняются в каталог settings.MEDIA_ROOT
, не учитывая дополнительных параметров. Похоже, что функция upload_by_conditions
не работает во время миграции. Причину такого поведения пока осознать не могу.
Есть идеи?
Updated 8 Dec. 2012, 13:09 by RaD.