首页 > 解决方案 > 在导入之前检查 .csv 文件的格式是否正确,以避免将错误的数据嵌入数据库

问题描述

我正在开发一个 django 项目,该项目需要使用以 excelsheet 格式提供的批量数据更新数据库。所以基本上,如果 .csv 文件的格式正确(我的意思是正确的格式,我期望的数据格式良好的文件),用户可以上传 .csv 文件。我知道如何使用 django-import-export 导入文件,但问题是,我不知道如何执行检查,例如在更新数据库之前检查 .csv 文件是否具有正确的列名和信息。我是django的新手,请帮忙。

标签: pythondjangodjango-import-export

解决方案


检查格式正确的文件

如果您正在以编程方式导入文件,那么如果您可以加载 Dataset 对象,而不会引发任何错误,那么它就是一个格式正确的 csv 文件。所以像:

try:
  with open('data.csv', 'r') as fh:
    imported_data = Dataset().load(fh, headers=False)
except Exception as e:
  # you can add additional error handling / logging here if you like
  print("import fail")
  raise e

检查正确的标题

在导入过程之前,您可以使用一个挂钩来检查有效的标头。因此,您可以执行以下操作来检查缺少的列:

class YourResource(resources.ModelResource):
    fields = ('author', 'email')

    def before_import(self, dataset, using_transactions, dry_run, **kwargs):
        for field_name in self.fields:
            col_name = self.fields[field_name].column_name
            if col_name not in dataset.headers:
                raise ValueError(f"'{col_name}' field not in data file")

数据验证

您可以使用内置小部件在字段级别提供额外的验证。您可以随心所欲地扩展它们,以启用额外的特定于域的验证。例如,如果您只想允许 '1' 或 0' 作为布尔值,则可以实现以下内容:

class StrictBooleanWidget(widgets.BooleanWidget):
    TRUE_VALUES = ["1"]
    FALSE_VALUES = ["0"]
    NULL_VALUES = [""]

    def clean(self, value, row=None, *args, **kwargs):
        if value in self.NULL_VALUES:
            return None
        if value in self.TRUE_VALUES:
            return True
        if value in self.FALSE_VALUES:
            return False
        raise ValueError("Invalid boolean: value must be 1 or 0.")

然后在你的资源中参考这个:

class YourResource(resources.ModelResource):
    is_active = fields.Field(
        attribute="active",
        column_name="active",
        default=False,
        widget=upload.widgets.StrictBooleanWidget(),
    )

您还可以使用此方法检查数据中的缺失值或空值。

django-import-export确实对您描述的用例有很大帮助,但是当您不熟悉它时可能会感到困惑。深入阅读文档,我建议下载并运行示例应用程序(如果您还没有的话)。

核心导入逻辑相当简单,但如果您可以在开发过程中设置断点并逐步执行,它将节省大量时间。这将真正帮助您了解正在发生的事情。


推荐阅读