使用通过django admin上传的文件元数据填充模型
我有两种型号,使用通过django admin上传的文件元数据填充模型,django,file-upload,django-models,django-admin,Django,File Upload,Django Models,Django Admin,我有两种型号,Foto和fotomatadataFoto只有一个名为upload的属性,即upload字段FotoMetadata有一些属性,应该从上传到foto的foto接收元数据。这可以在管理界面手动完成,但我想自动完成,即:通过管理界面上传照片时,FotoMetadata会自动填充 在我的model.py中,我有几个类,包括Foto和FotoMetadata: class Foto(models.Model): upload = models.FileField(upload_to
Foto
和fotomatadata
Foto
只有一个名为upload的属性,即upload字段FotoMetadata
有一些属性,应该从上传到foto
的foto接收元数据。这可以在管理界面手动完成,但我想自动完成,即:通过管理界面上传照片时,FotoMetadata
会自动填充
在我的model.py中,我有几个类,包括Foto和FotoMetadata:
class Foto(models.Model):
upload = models.FileField(upload_to="fotos")
def __str__(self):
return '%s' %(self.upload)
class FotoMetadata(models.Model):
image_formats = (
('RAW', 'RAW'),
('JPG', 'JPG'),
)
date = models.DateTimeField()
camera = models.ForeignKey(Camera, on_delete=models.PROTECT)
format = models.CharField(max_length=8, choices=image_formats)
exposure = models.CharField(max_length=8)
fnumber = models.CharField(max_length=8)
iso = models.IntegerField()
foto = models.OneToOneField(
Foto,
on_delete=models.CASCADE,
primary_key=True,
)
当我登录管理站点时,我有一个与Foto
相关的上传表单,这很正常。我的问题是,我不能在移动中插入元数据。我做了一个函数来解析照片,并给我一个字典,里面有我需要的信息。此函数名为GetExif,位于名为GetExif.py的文件中。这将是它的简化版本:
def GetExif(foto):
# Open image file for reading (binary mode)
f = open(foto, 'rb')
# Parse file
...
<parsing code>
...
f.close()
#create dictionary to receive data
meta={}
meta['date'] = str(tags['EXIF DateTimeOriginal'].values)
meta['fnumber'] = str(tags['EXIF FNumber'])
meta['exposure'] = str(tags['EXIF ExposureTime'])
meta['iso'] = str(tags['EXIF ISOSpeedRatings'])
meta['camera'] =str( tags['Image Model'].values)
return meta
我原以为它会起作用,或者我在将数据保存到模型时会遇到问题,但实际上我在这之前就被绊倒了。我得到了这个错误:
异常类型:FileNotFoundError
异常值:[Errno 2]没有这样的文件或目录:“” 异常位置:/home/ricardo/Desenvolvimento/fotosite/fotomanager/local/getexif.py,在getexif中,第24行 我的GetExif函数无法读取文件,但是,文件路径是正确的!如果我复制并粘贴到浏览器,它将下载文件。我试图找出一种方法来更正地址,或者传递内部路径,或者将实际文件传递给函数而不是其路径。我也在考虑在GetExif()函数中访问文件的不同方法。你知道怎么解决吗
解决方案 我解决了上面的问题!通过阅读FileField源代码,我找到了一个名为
path
的属性,它解决了这个问题。我还做了一些其他的修改,代码正在运行。FotoAdmin类,位于admin.py现在是这样的:
class FotoAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# populate the model
obj.save()
# get metadata
metadados = GetExif(obj.upload.path)
# Create instance of FotoMetadata
fotometa = FotoMetadata()
# FotoMetadata.id = Foto.id
fotometa.foto = obj
# set and save exposure
fotometa.exposure = metadados['exposure']
fotometa.save()
我还必须在models.py中的一些属性上设置
null=True
,并且一切都正常工作。我猜您希望启用post\u保存信号
阅读:
激活post_save信号-这样在保存FOTO之后,就有了一个钩子来做其他事情,在您的例子中,解析photometa并创建一个FotoMetadata实例
此外,如果您希望仅在fotometa成功时保存foto,或您可能使用的任何其他条件,请在保存meta foto后预保存信号并仅保存foto。我进行了研究,并使用
保存模型
结束。但我在访问上传的文件时遇到问题。我只能在Instance上访问它。我用更多信息编辑了原始帖子。第24行是f=open(foto,'rb')
。谢谢你的帮助,当我刚结巴的时候,它帮了我很多。我已经解决了问题并发布了解决方案!谢谢
class FotoAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# populate the model
obj.save()
# get metadata
metadados = GetExif(obj.upload.path)
# Create instance of FotoMetadata
fotometa = FotoMetadata()
# FotoMetadata.id = Foto.id
fotometa.foto = obj
# set and save exposure
fotometa.exposure = metadados['exposure']
fotometa.save()