#python #fileupload #django
Здравствуйте, В django до версии 1.4 была возможность в модели для models.FileField указать "динамически" создаваемый путь хранения файлов в переменную upload_to models.py #... attach = models.FileField(verbose_name=u'Приложение', blank=True, upload_to=lambda instance, filename: 'attach/%s/%s' % (instance.id,filename)) D django версии 1.4 похоже id присваивается позже и поэтому instance.id = None и так же instance.pk = None. Подскажите как можно указать в путь именно id модели.
Ответы
Ответ 1
Ваш вопрос немного ставит в тупик, потому как лично у меня в версии до 1.4 также id не был доступен в upload_to. Вообще вопрос хранения путей файлов достаточно избит. По мне, так самый нормальный вариант с построением хеша от timestamp + имя файла и создание директорий по первым 4м символам хеша upload_to = 'upload_path/%s/%s/%s.jpg' % (hash[:1], hash[2:3], hash) UPDATE Касательно именно id в имени файла. Вам надо после сохранения файла, т.е. после присвоения id в базе генерировать новый путь и соответственно перемещать файл по новому пути. На мое субъективное мнение уж слишком затратная операция получается. UPDATE2 import uuid def get_file_path(instance, filename): ext = filename.split('.')[-1] filename = "%s.%s" % (uuid.uuid4(), ext) return 'uploads/%s/%s/%s.jpg' % (filename[:1], filename[2:3], filename) и в модели file = models.FileField(upload_to=get_file_path, null=True, blank=True, verbose_name=_(u'Contact list'))Ответ 2
Согласно документации для версий до 1.4 включительно: In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field Соответсвенно, такое поведение было и раньше, возможно вы ошиблись. Да, можно сделать грязный хак для решения этой проблемы с отлавливанием сигнала сохранения модели и перемещения файла по новому пути... надо ли оно вам - это должны решить сами. Либо, раз уж в документации говорится именно об AutoField, попробуйте заменить поле id у модели на что-то свое (хэш от файла? UUID? Сами решайте). Возможно, этот трюк сработает.Ответ 3
ID будет только после вставки ряда, а ряд вставится только после записи всех полей. Поэтому нельзя знать ID пока объект не сохранен. Самое простое — в транзакции сначала сохранить с attach=None, потом обновить поле и пересохранить. Как-то в таком духе: with transaction.commit_on_success(): file = File(..., attach=None) file.save() file.attach = attachment file.save() В рамках оптимизации можно сделать предвыборку ID, но это не очень красиво и vendor-specific решение, которое сложно переносить между базами данных. Зато избавляет от пары INSERT+UPDATE, ограничиваясь одной вставкой. Для PostgreSQL, который умеет SEQUENCEs, например будет что-то в духе: from django.db import connection assert connection.vendor == "postgresql" cursor = connection.cursor() cursor.execute("SELECT nextval('seq_files_id')") new_id, = cursor.fetchone() file = File(id=new_id, ...) file.save()
Комментариев нет:
Отправить комментарий