使用通过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()