我正在尝试使用默认的Django admin创建一个简单的照片库。我想为每个画廊保存一张样本照片,但我不想保留filname。除了文件名,我想保存模型的ID(N.jpg)。但是,第一次我要保存该对象时,该ID不存在。我如何知道模型中的下一个自动增量,或者以某种方式保存模型数据(在存在super.save文件时上传之前和之后)self.id?有没有很酷的解决方案?
N.jpg
super.save
self.id
像这样:
def upload_path_handler(instance, filename): ext = filename extension return "site_media/images/gallery/{id}.{ext}".format(id=instance.nextincrement, ext=ext) class Gallery(models.Model): name = models.TextField() image = models.FileField(upload_to=upload_path_handler)
也许将文件名存储在其他字段中。
图像文件将在Gallery实例之前保存。因此,您必须通过使用带有状态的Gallery实例本身的信号将保存分为两个阶段:
from django.db.models.signals import post_save, pre_save from django.dispatch import receiver _UNSAVED_FILEFIELD = 'unsaved_filefield' @receiver(pre_save, sender=Image) def skip_saving_file(sender, instance, **kwargs): if not instance.pk and not hasattr(instance, _UNSAVED_FILEFIELD): setattr(instance, _UNSAVED_FILEFIELD, instance.image) instance.image = None @receiver(post_save, sender=Image) def save_file(sender, instance, created, **kwargs): if created and hasattr(instance, _UNSAVED_FILEFIELD): instance.image = getattr(instance, _UNSAVED_FILEFIELD) instance.save() # delete it if you feel uncomfortable... # instance.__dict__.pop(_UNSAVED_FILEFIELD)
upload_path_handler看起来像
def upload_path_handler(instance, filename): import os.path fn, ext = os.path.splitext(filename) return "site_media/images/gallery/{id}{ext}".format(id=instance.pk, ext=ext)
如果字段仅用于图像上传,我建议使用ImageField而不是FileField进行类型检查。另外,您可能希望规范化文件名扩展名(由于mimetype而不需要),例如
def normalize_ext(image_field): try: from PIL import Image except ImportError: import Image ext = Image.open(image_field).format if hasattr(image_field, 'seek') and callable(image_field.seek): image_field.seek(0) ext = ext.lower() if ext == 'jpeg': ext = 'jpg' return '.' + ext
我遇到了同样的问题。Okm的答案使我走上了正确的道路,但在我看来,仅通过重写save()Model 的方法就可以实现相同的功能。
def save(self, *args, **kwargs): if self.pk is None: saved_image = self.image self.image = None super(Material, self).save(*args, **kwargs) self.image = saved_image super(Material, self).save(*args, **kwargs)
这肯定可以正确保存信息。