我有两个模型,Foto
和FotoMetadata
。 Foto
只有一个名为upload的属性,即上传字段。 FotoMetadata
有一些属性,应该从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
相关的上传表单,这个工作正常。我的问题是我无法在移动中FotoMetadata
插入元数据。我做了一个解析照片的函数,并给我一本包含我需要的信息的字典。此函数名为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
所以,基本上,我尝试做的是使用admin.py中的此功能在FotoMetadata
上传照片时自动填充Foto
,但我真的无法&#39 ;弄清楚如何制作它。有人有线索吗?
编辑2016年3月24日
好的,经过多次失败后,我尝试在 admin.py 中使用 save_model :
from django.contrib import admin
from .models import Autor, Camera, Lente, Foto, FotoMetadata
from fotomanager.local.getexif import GetExif
admin.site.register(Autor)
admin.site.register(Camera)
admin.site.register(Lente)
admin.site.register(FotoMetadata)
class FotoAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# populate the model
obj.save()
# get metadata
metadados = GetExif(obj.upload.url)
# Create instance of FotoMetadata
fotometa = FotoMetadata()
# FotoMetadata.id = Foto.id
fotometa.foto = obj.pk
# save exposure
fotometa.exposure = metadados['exposure']
admin.site.register(Foto, FotoAdmin)
我认为它会起作用,或者我会在将数据保存到模型时遇到问题,但实际上我在此之前就被困住了。我收到了这个错误:
异常类型:FileNotFoundError 例外价值:
[Errno 2]没有这样的文件或目录:&#39; http://127.0.0.1:8000/media/fotos/IMG_8628.CR2&#39; 例外地点:GetHif中的/home/ricardo/Desenvolvimento/fotosite/fotomanager/local/getexif.py,第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
,一切正常。
答案 0 :(得分:1)
我想你想要为post_save启用一个信号 阅读:django signals
激活post_save信号 - 所以在保存FOTO之后,你有一个钩子来做其他事情,在你的案例中解析photometa并创建一个FotoMetadata实例。
更多,如果你想只在fotometa成功或你可能使用的任何其他条件下保存foto,pre_save信号并保存foto仅在保存meta foto之后。