在上传文件和保存模型之前挂钩

时间:2014-04-09 12:23:47

标签: django filefield

我是django的新手并尝试实现一个允许用户上传文件,解析并将包含的信息输入同一模型的项目:

class Track(models.Model):  
    Gpxfile  = models.FileField("GPS XML", upload_to="tracks/gps/")
    date=models.DateTimeField(blank=True)
    waypoints = models.ForeignKey(Waypoint)
    ...

首先,我可以使用管理界面并保存工作。所以我迷上了模型save()方法:

def save(self, *args, **kwargs):
    """we hook to analyse the XML files"""
    super(Track, self).save(*args, **kwargs) #get the GPX file saved first
    self.__parseGPSfile(self.Gpsxmlfile.path) #then analyse it

但是,由于依赖,我遇到了问题:

  • 要将文件字段保存到真实文件,我需要先调用原始的save()
    • 由于某些字段尚未填充,因为我没有填充
  • 如果我切换两行,则文件尚未保存且无法解析

也许我只缺乏基本知识,但即使在阅读了很多SO,博客和googeling后,我也不清楚如何解决它。我刚刚发现这些想法看起来不太合适:

  • 创建自己的视图并将其连接到处理程序(see here
    • 糟糕,因为这不适用于管理界面,需要视图,将逻辑放到视图等...
  • 使用验证器作为文件字段(see here
    • 不确定这是不是一个好的设计,因为它是关于文件处理的一般而不是真正的验证(还)

那么社区建议在Django 1.4中实现文件后处理和数据“导入”?

1 个答案:

答案 0 :(得分:2)

您可以在保存之前解析文件,通常我喜欢在模型clean()方法中执行此操作:

def clean(self):
    file_contents = self.Gpxfile.read()
    ...do stuff

如果文件不符合您的验证标准,您可以在clean中引发ValidationError,它将传播回调用视图,以便您可以将表单错误报告给用户。

如果您确实需要先保存文件然后再做一些事情,可以使用post_save信号

def some_function_not_in_the_model(sender, **kwargs):
    obj = kwargs['instance']
    ...do stuff with the object

# connect function to post_save
post_save.connect(some_function_not_in_the_model, sender=Track)

Django docs on post_save

最后,关于大文件的一个注意事项是它们可能最终作为服务器上的临时文件(在Linux / var / tmp或类似文件中......这可以在settings.py中设置)。在尝试访问文件时,在clean()方法中检查此信息可能是个好主意,例如:

# check if file is temporary
if hasattr(self.Gpxfile.file, 'temporary_file_path'):
    try:
        file_path = self.Gpxfile.file.temporary_file_path(),
    except:
        raise ValidationError(
            "Something bad happened"
        )
else:
    contents = self.Gpxfile.read()

哦,最后,小心关闭临时文件。回到我开始使用Django的FileField并了解临时文件是如何工作的时候,我以为我会成为优秀的程序员并在完成使用后关闭文件。这会导致问题,因为Django将在内部执行此操作。同样,如果您打开临时文件并引发ValidationError,您可能希望删除(取消链接)临时文件以防止它们累积在临时目录中。

希望这有帮助!