【问题标题】:Populate model with metadata of file uploaded through django admin使用通过 django admin 上传的文件元数据填充模型
【发布时间】:2016-07-11 07:27:35
【问题描述】:

我有两个模型,FotoFotoMetadataFoto 只有一个属性称为上传,即上传字段。 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 中使用此功能在Foto 上传照片时自动填充FotoMetadata,但我真的不知道如何制作它.有人知道吗?


编辑 24/03/2016

好的,在多次失败之后,我正在尝试在 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] 没有这样的文件或目录:'http://127.0.0.1:8000/media/fotos/IMG_8628.CR2' 异常位置:GetExif 中的 /home/ricardo/Desenvolvimento/fotosite/fotomanager/local/getexif.py,第 24 行

我的 GetExif 函数无法读取文件,但是,文件路径是正确的!如果我将它复制并粘贴到我的浏览器,它会下载该文件。我试图找出一种方法来更正地址,或者传递内部路径,或者将真实文件传递给函数而不是它的路径。我也在考虑一种在 GetExif() 函数中访问文件的不同方法。知道如何解决吗?


解决方案

我解决了上面的问题!通过阅读 FileField 源代码,我发现了一个名为 path 的属性,它解决了这个问题。我还进行了一些其他修改,代码正在运行。 admin.py 中的 FotoAdmin 类现在是这样的:

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,并且一切正常。

【问题讨论】:

    标签: django file-upload django-models django-admin


    【解决方案1】:

    我猜你想启用 post_save 一个信号 阅读:django signals

    激活 post_save 信号 - 因此,在您保存 FOTO 后,您有一个钩子可以做其他事情,在您的情况下解析 photometa 并创建一个 FotoMetadata 实例。

    此外,如果您想仅在 fotometa 成功或您可能使用的任何其他条件下保存照片,请 pre_save 发出信号并仅在保存元照片后保存照片。

    【讨论】:

    • 我做了一个研究,最后使用save_model。但是我在访问上传的文件时遇到问题。我只能访问它。我用更多信息编辑了原始帖子。
    • 第 24 行是f = open(foto, 'rb')。感谢您的帮助,当我刚刚卡住时,它帮助了我很多。我已经解决了问题并发布了解决方案!谢谢!
    猜你喜欢
    • 2012-04-16
    • 1970-01-01
    • 2017-03-17
    • 2016-02-05
    • 2011-08-30
    • 2020-07-23
    • 2019-12-04
    • 2013-03-03
    • 1970-01-01
    相关资源
    最近更新 更多