Skip to main content

用于将结构化数据导入 Django 模型的基于 Web 的交互式向导。

项目描述

Django Data Wizard是一个交互式工具,用于通过Django REST FrameworkIterTable将表格数据(例如 Excel、CSV、XML、JSON)映射到规范化的数据库结构中。Django Data Wizard 允许新手用户在导入过程中即时将电子表格列映射到序列化器字段(并将单元格值映射到外键)。这减少了对大多数数据导入解决方案所需的预设电子表格格式的需求。

列选择 自动导入 - 进度条 导入记录

数据向导支持从电子表格列到数据库字段的直接一对一映射,以及更复杂的场景,如自然键实体-属性-值(或“宽”)表映射。它最初是为与vera提供的ERAV 数据模型一起使用而开发的。

最新的 PyPI 版本 发行说明 执照 GitHub 星星 GitHub 叉子 GitHub 问题

测试 Python 支持 Django 支持

用法

Django Data Wizard 提供了一个Web 界面JSON APICLI,用于指定要导入的数据源(例如以前上传的文件)、选择序列化程序、映射数据标识符,以及(异步)将数据导入任何目标数据库中的模型。

数据向导旨在允许用户迭代地优化他们的数据导入流程。例如,在初始数据导入期间做出的决定将保留用于将来导入具有相同结构的文件。包含的数据模型使这个工作流程成为可能。

目录

  1. 入门
  2. API 文档
  3. 高级定制

安装

# Recommended: create virtual environment
# python3 -m venv venv
# . venv/bin/activate

python3 -m pip install data-wizard

请参阅https://github.com/wq/django-data-wizard报告任何问题。

初始配置

在新的或现有的 Django 项目中,添加data_wizard到您的INSTALLED_APPS

# myproject/settings.py
INSTALLED_APPS = (
   # ...
   'data_wizard',
   'data_wizard.sources',  # Recommended
)

# This can be omitted to use the defaults
DATA_WIZARD = {
    'BACKEND': 'data_wizard.backends.threading',
    'LOADER': 'data_wizard.loaders.FileLoader',
    'IDMAP': 'data_wizard.idmap.existing',
    'AUTHENTICATION': 'rest_framework.authentication.SessionAuthentication',
    'PERMISSION': 'rest_framework.permissions.IsAdminUser',
    'AUTO_IMPORT_TASKS': (
        'data_wizard.tasks.check_serializer',
        'data_wizard.tasks.check_iter',
        'data_wizard.tasks.check_columns',
        'data_wizard.tasks.check_row_identifiers',
        'data_wizard.tasks.import_data',
    ),
}

如果你想使用内置的数据源表(FileSourceURLSource),也包括data_wizard.sources在你的INSTALLED_APPS. 否则,您将需要配置一个或多个自定义数据源(见下文)

注意:默认情况下,Django 数据向导使用简单的线程后端来执行异步任务。 可以使用Celery 和 Redis代替,但这不是必需的。

接下来,添加"data_wizard.urls"到您的 URL 配置。

# myproject/urls.py
from django.urls import path, include

urlpatterns = [
    # ...
    path('datawizard/', include('data_wizard.urls')),
]

目标模型注册

为了使用该向导,您必须注册一个或多个目标模型和/或序列化程序。目标模型注册可帮助向导知道将其在源电子表格的每一行中找到的数据放在何处。(相比之下,只要您使用提供的应用程序,data_wizard.sources模型注册是可选的。)

注册 API 仿照 Django admin 和admin.py. 具体来说,Data Wizard 将wizard.py在您的应用程序目录中查找一个文件,该文件应具有以下结构:

# myapp/wizard.py
import data_wizard
from .models import MyModel

data_wizard.register(MyModel)

在内部,该向导将自动创建一个与目标模型对应的 Django REST Framework 序列化程序类。如果需要,您还可以指定自定义序列化程序类来配置目标模型的验证和填充方式。

配置完所有内容后,在 Django 管理中上传源文件,从管理操作菜单中选择“通过数据向导导入”,然后浏览下面描述的屏​​幕。

API 文档

Django 数据向导被实现为一系列视图,可以通过 Django 管理员以及 JSON API 访问。


选择来源并开始导入

新运行

POST /datawizard/

创建向导的新实例(即 a Run)。如果您使用的是 Django 管理集成,则在您从管理操作菜单中选择“通过数据向导导入”时执行此步骤。如果您使用的是 JSON API,则返回的运行id应用于对该 API 的所有后续调用。每个Run都通过通用外键绑定到源模型。

范围 描述
object_id 包含要导入的数据的模型实例的主键。
content_type_id 模型的应用标签和模型名称(格式为app_label.modelname)。
loader (可选)用于通过IterTable加载源数据集的类名。默认 loader( data_wizard.loaders.FileLoader) 假定源模型包含一个FileField命名的file.
serializer (可选)填充目标模型时使用的序列化程序类。这可以不设置,以允许用户在向导运行期间选择目标。

自动导入 - 进度条

汽车

POST /datawizard/[id]/auto

auto任务尝试从头到尾运行整个数据向导过程。如果需要任何输入,导入将停止并重定向到必要的屏幕。如果不需要输入,则auto任务相当于data直接启动任务。这是一个异步方法,并返回一个task_id用于状态 API 的。

run_detail.html模板提供了一个启动任务的示例表单autoauto任务本身使用run_auto.html模板

默认任务序列由AUTO_IMPORT_TASKS设置定义。 注意,check_*任务不提供直接的 UI 或 HTTP API。data_wizard.InputNeeded相反,这些任务会在必要时通过引发重定向到相应的 UI 任务。例如,如果电子表格包含意外的列标题,则会data_wizard.tasks.check_columns引发InputNeeded并重定向到列任务。提交表单后,updatecolumns任务会处理用户输入并再次运行检查。一旦检查成功(即所有列都已映射),用户就可以重新启动自动任务。

以下是默认顺序中每个任务对应的输入和表单处理任务:

自动任务 输入任务 表单处理任务
check_serializer list_serializers updateserializer
check_iter 不适用 不适用
check_columns read_columns update_columns
check_row_identifiers read_row_identifiers update_row_identifiers
import_data 不适用 不适用

有关定义任务序列的详细信息,请参阅自定义任务。

资源:data_wizard.tasks.auto_import


地位

GET /datawizard/[id]/status.json?task=[task]

statusAPI 用于检查异步任务的状态(auto或之一data)。提供的data_wizard/js/progress.js使用该 API来更新run_auto.htmlrun_data.html模板<progress>中的栏。与其他方法不同,此 API 仅 JSON 且没有 HTML 等效项。将返回以下格式的对象:

{
    // General properties
    "status": "PROGRESS", // or "SUCCESS", "FAILURE"
    "stage": "meta",      // or "data"
    "current": 23,        // currently processing row
    "total": 100,         // total number of rows
    
    // "FAILURE"
    "error": "Error Message",

    // Task complete ("SUCCESS")
    "action": "records",        // or "serializers", "columns" "ids"
    "message": "Input Needed",  // if action is not "records"
    "skipped": [...],           // rows that could not be imported
    "location": "/datawizard/[id]/records",
}

status字段的潜在值与常见的Celery 任务状态相同,即使不使用celery后端也是如此。运行auto任务时,SUCCESS只要任务没有错误地结束,即使需要额外的输入来完全完成运行,结果也是如此。

默认的run_auto.htmlrun_data.html模板包含一个<progress>用于状态任务的元素。


串行器选择

序列化器

GET /datawizard/[id]/serializers

serializers任务提供了所有已注册序列化程序(即目标模型)的列表。auto如果在创建序列化程序时未指定序列化程序,则任务会显示此屏幕Run。默认的run_serializers.html模板包括一个用于选择目标的界面。如果已经选择了序列化程序,模板将显示标签和一个按钮来(重新)启动auto任务。

资源:data_wizard.tasks.list_serializers



选择的串行器

更新序列化程序

POST /datawizard/[id]/updateserializer

updateserializer任务Run使用选定的目标序列化程序名称更新指定。这通常从任务生成的表单serializers中调用,并在完成时重定向到该任务。

范围 描述
serializer 用于此运行的目标序列化程序的类名(或标签)。

资源:data_wizard.tasks.updateserializer


列选择

GET /datawizard/[id]/columns

columns任务列出了在源数据集(即电子表格)中找到的所有列以及它们到目标序列化器字段的映射。auto如果有任何列名无法自动映射,则任务会显示此屏幕。潜在的映射是以下之一:

  • 简单的序列化器字段名称(例如field
  • 嵌套字段名称(用于自然键,例如nested[record][field]
  • EAV属性值映射(例如values[][value];attribute_id=1)。请注意,EAV 支持需要自定义序列化程序类

默认的run_columns.html模板包含一个用于将数据列映射到序列化器字段的接口。如果所有列都已映射,则模板将显示映射和用于(重新)启动auto任务的按钮。

资源:data_wizard.tasks.read_columns


选定的列

更新列

POST /datawizard/[id]/updatecolumns

updatecolumns任务保存从源数据列到目标序列化器字段的指定映射。这通常从任务生成的表单columns中调用,并在完成时重定向到该任务。

范围 描述
rel_[relid] 要映射到指定序列化器字段的列。任务relid将提供可能映射的完整列表。columns

资源:data_wizard.tasks.update_columns


标识符选择

身份证

GET /datawizard/[id]/ids

ids任务列出了在源数据集(即电子表格)中找到的所有外键值。如果有任何未映射的外键值,自动任务将停止并重定向到该ids任务。默认的run_ids.html模板包括一个用于将行标识符映射到外键值的接口。潜在的映射取决于用于表示外键的序列化器字段。

映射完所有 id 后,模板将显示映射和一个用于(重新)启动auto任务的按钮。

请注意,如果以下任何一项为真,则该auto任务将完全跳过该ids任务:

  • 该文件不包含外键列
  • 在上一次导入运行期间已映射所有外键值
  • 所有外键值都可以通过DATA_WIZARD['IDMAP']设置自动映射:
DATA_WIZARD['IDMAP'] 细节
"data_wizard.idmap.existing"(默认) 自动映射现有 ID,但需要用户映射未知 ID
"data_wizard.idmap.never" 要求用户在文件中第一次找到所有 ID 时手动映射它们
"data_wizard.idmap.always" 始终映射 ID(跳过手动映射)。未知 ID 将按原样传递给序列化程序,这将导致每行错误,除非使用自然键。
(自定义导入路径) 该函数应该接受一个标识符和一个序列化器字段,并返回映射的值(或者None如果没有自动映射可用)。有关示例,请参见内置函数

请注意,配置的IDMAP函数只会在第一次遇到新标识符时被调用。一旦建立映射(手动或自动),它将在后续的向导运行中重新使用。

资源:data_wizard.tasks.read_row_identifiers


选择的标识符

更新ID

POST /datawizard/[id]/updateids

updateids任务保存从行标识符到外键值的指定映射。这通常从任务生成的表单ids中调用,并在完成时重定向到该任务。

范围 描述
ident_[identid]_id 要映射到指定外键值的标识符。任务identid将提供可能映射的完整列表。ids

资源:data_wizard.tasks.update_row_identifiers


自动导入 - 进度条

数据

POST /datawizard/[id]/data

data任务启动实际的导入过程(并auto在幕后调用)。与 不同的是,如果需要任何元输入auto,直接调用data不会导致重定向到其他任务之一。相反,data将尝试按原样导入每条记录,并报告由于例如缺少字段或未映射的外键而发生的任何错误。

这是一个异步方法,并返回一个task_id用于statusAPI 的方法。默认的run_data.html模板包含一个<progress>用于状态任务的元素。

资源:data_wizard.tasks.import_data


导入记录

记录

GET /datawizard/[id]/records

records任务提供导入行的列表(包括错误)。完成后由autoand任务重定向到。data成功导入Record的实例将具有指向目标模型的通用外键。records任务将包含指向get_absolute_url()每个新导入的目标模型实例的管理屏幕的链接。默认的run_records.html模板包含一个用于显示记录详细信息的界面。



运行列表

运行列表

GET /datawizard/

Django 数据向导提供了一个列表视图,它总结了以前的运行和每次导入的记录数。也可以从此列表重新启动未完成的运行。




标识符管理员

标识符管理员

GET /admin/data_wizard/identifer/

可以通过 Django Admin 查看和编辑 Django 数据向导标识符映射。运行也可以通过管理员查看 - 尽管上面的运行列表通常会更有用。


数据模型

Django Data Wizard 提供了许多 Django 模型来帮助跟踪导入过程,并保留数据映射决策以供将来重用。虽然需要模型,但您的目标数据模型通常无需更改即可支持数据向导集成。

描述 模型
0 上传文件 创建FileSource(或自定义源模型)
1 开始数据向导运行 创造Run
2 选择序列化程序(和目标模型) 更新Run
3 将列映射到数据库字段名称 Identifier如果需要,每列一个
4 将单元格值映射到外键 Identifier每个唯一值一个
5 将数据导入目标模型 每行一个Record+ 一个目标模型实例

Run模型包括一个指向源模型的通用外键FileSource(例如。)源电子表格中的每一行都将映射到一个Record. 如果成功导入该行,将创建目标数据模型的新实例,并且Record将有一个指向它的通用外键。该Identifier模型不包含外键,因为标识符映射被重复用于后续导入。相反,一个单独的模型跟踪 each中每个Range的位置(行/列)。IdentifierRun

请注意,上述工作流程仅描述了最常见的用例。您可以创建自定义序列化程序,为每个电子表格行更新多个目标数据模型。您可以指定可能不是电子表格甚至文件的自定义数据源。

命令行界面

Django Data Wizard 提供了一个单一的管理命令runwizard,可用于auto从命令行启动任务。这可用于促进自动化处理,例如作为常规 cron 作业的一部分。请注意,CLI(当前)不支持交互式映射列和 ID,因此应使用 Web 或 JSON API 预先映射这些列和 ID。

用法:

./manage.py runwizard myapp.mymodel 123 \
    --loader myapp.loaders.customloader \
    --serializer myapp.serializer.customserializer \
    --username myusername

基本用法与New Run API类似。仅需要内容类型和对象 ID,而其他参数将在可能的情况下自动检测。特别是,您可能希望使用set_loader()来预定义默认值loader以及serializer您计划与 CLI 一起使用的任何模型。

runwizard命令将创建一个新的Run并立即启动该auto任务。错误将显示在控制台上。

自定义序列化器

数据向导使用 Django REST Framework 的Serializer 类的实例来确定目标模型上的目标字段。具体来说,默认的序列化器是NaturalKeyModelSerializer,它基于ModelSerializer

data_wizard.register()您可以通过使用名称和序列化程序类而不是模型类调用来覆盖默认序列化程序。可以使用向导注册多个序列化程序以支持多个导入配置和目标模型。

# myapp/wizard.py
from rest_framework import serializers
import data_wizard
from .models import TimeSeries


class TimeSeriesSerializer(serializers.ModelSerializer):
    # (custom fields here)
    class Meta:
        model = TimeSeries
        fields = '__all__'

        # Optional - see options below
        data_wizard = {
            'header_row': 0,
            'start_row': 1,
            'show_in_list': True,
            'idmap': data_wizard.idmap.existing,
            'auto_import_tasks': [ custom task list ],
        }

# Use default name & serializer
data_wizard.register(TimeSeries)

# Use custom name & serializer
data_wizard.register("Time Series - Custom Serializer", TimeSeriesSerializer)

至少应注册一个序列化程序或模型才能使用该向导。请注意在注册序列化程序时使用人性化的序列化程序标签。此名称在整个项目中应该是唯一的,但以后可以在不破坏现有数据的情况下进行更改。(类路径用作幕后的实际标识符。)

串行器选项

通常,自定义序列化程序具有常规Django REST 框架序列化程序的所有功能,包括自定义验证规则和填充多个目标模型的能力。虽然request上下文不可用,但可以通过上下文检索有关运行(包括用户)的信息data_wizard

当为自然键模型重写序列化器时,一定要扩展NaturalKeyModelSerializer,如本例所示。在其他情况下,扩展ModelSerializer(如上例所示)或基本Serializer类。

自定义序列化程序可用于支持实体-属性-值电子表格,其中属性名称被指定为附加列。为了支持这种情况,Entity序列化程序应该包含一个嵌套的Value序列化程序many=True,并且Value序列化程序应该有一个表的外键Attribute,如本例所示

数据向导还通过在序列化程序的类data_wizard上设置属性来支持其他配置。Meta支持以下选项。

姓名 默认 笔记
header_row 0 指定包含列标题的电子表格的第一行。如果该值大于 0,则将扫描列标题上方的空间以查找任何看起来像一次性“全局”值的内容,该值旨在应用于导入数据中的每一行。
start_row 1 第一行数据。如果大于header_row + 1,则假定列标题跨越多行。一个常见的情况是 EAV 参数名称在第一行,单位在第二行。
show_in_list True 如果设置为False,序列化程序将通过 API 可用,但不会在向导视图中列出。如果您有一个仅应在完全自动化的工作流程中使用的序列化程序,这将非常有用。
idmap IDMAP环境 可以是任何data_wizard.idmap.*函数或自定义函数。与IDMAP设置不同,这应该始终是实际功能,而不是导入路径。
auto_import_tasks AUTO_IMPORT_TASKS环境 注册函数的导入路径列表@data_wizard.wizard_task(请参阅自定义任务

自定义数据源

Django Data Wizard 使用IterTable来确定电子表格或其他数据源中存在的源列。Django Data Wizard 可以使用任何 Django 模型实例作为其数据的源,只要有一个注册的加载器可以将源模型转换为Iter 类。Data Wizard 提供了两个开箱即用的加载器FileLoaderURLLoader,它们可以分别与data_wizard.sources(FileSourceURLSource) 中提供的模型一起使用。

扩展文件加载器

默认值FileLoader可用于任何具有FileField命名的 Django 模型fileFileField您可以通过创建一个子类data_wizard.loaders.FileLoader并将其设置为模型的加载器来使用具有不同名称的模型。

# myapp/models.py
from django.db import models

class FileModel(models.Model):
    spreadsheet = models.FileField(upload_to='spreadsheets')
# myapp/loaders.py
from data_wizard import loaders

class FileLoader(loaders.FileLoader):
    file_attr = 'spreadsheet'
# myapp/wizard.py
import data_wizard
from .models import FileModel

data_wizard.set_loader(FileModel, "myapp.loaders.FileLoader")

如果您有一个可以处理多个源模型的通用加载器,您还可以全局设置默认加载器:

# myapp/settings.py
DATA_WIZARD = {
    'LOADER': 'myapp.loaders.FileLoader'
}

您应该注册一个自定义ModelAdmin类以在您的模型的管理面板中添加导入操作。

# myapp/admin.py
from django.contrib import admin
from data_wizard.admin import ImportActionModelAdmin

from .models import FileModel


@admin.register(FileModel)
class FileModelAdmin(ImportActionModelAdmin):
    pass

自定义加载器

默认加载器支持IterTable支持的任何文件格式(Excel、CSV、JSON 和 XML)。可以通过创建自定义 IterTable 类然后将其注册到向导来集成其他格式。例如,Climata 查看器使用 Django 数据向导从climata的基于 IterTable 的 Web 服务客户端导入数据。为此,请使用从 IterTable 返回数据data_wizard.loaders.BaseLoader的自定义load_iter()函数进行扩展,如下例所示。

您可能希望在自定义加载程序中使用特定的序列化程序。如果是这样,请覆盖default_serializerget_serializer_name()在加载程序上。默认情况下,这些返回None,这需要用户在创建或执行时指定序列化程序Run

# myapp/models.py
from django.db import models

class CustomIterSource(models.Model):
    some_option = models.TextField()
# myapp/loaders.py
from data_wizard import loaders
from .iter import CustomIter

class CustomIterLoader(loaders.BaseLoader):
    default_serializer = 'mydataapp.wizard.CustomSerializer'
    def load_iter(self):
        source = self.run.content_object
        return CustomIter(some_option=source.some_option)
# myapp/wizard.py
import data_wizard
from .models import CustomIterSource

data_wizard.set_loader(CustomIterSource, "myapp.loaders.CustomIterLoader")

自定义任务

可以覆盖自动任务执行的任务序列,删除步骤或添加新步骤。该列表可以被全局覆盖(通过设置DATA_WIZARD['AUTO_IMPORT_TASKS']),或者基于每个序列化器(通过设置Meta.data_wizard['auto_import_tasks'])。

每个自定义任务函数都应该向@data_wizard.wizard_task装饰器注册,以配置标签和可选的 API 路径相对于/datawizard/[id]/. 装饰器和函数的参数决定了任务类型。

检查任务

@data_wizard.wizard_task(label="Custom Check", url_path=False)
def custom_check(run):
    if not some_condition_satisfied(run):
        raise data_wizard.InputNeeded("custominput")

检查任务验证是否满足某些条件,如果需要,重定向到输入任务。 url_path通常设置为 False 以禁用 HTTP 端点。任务标签将显示在进度条中(如果任务运行时间超过几秒钟)。

输入任务

@data_wizard.wizard_task(label="Custom Input", url_path="custominput")
def custom_input(run):
   return {"some_template_context": []}

输入任务使用户能够提供反馈以指导向导。它们应该有一个url_path(默认为函数名)和一个相应的模板(例如data_wizard/run_custominput.html)。任务返回的上下文将在result变量下的模板中。该模板通常会呈现带有所需输入的表单,或者(如果已输入所有输入)带有重新启动自动任务选项的摘要。

表单处理任务

@data_wizard.wizard_task(label="Custom Input", url_path="customsave")
def custom_save(run, post={}):
   some_save_method(run, post)
   return {
       **custom_input(run),
       "current_mode": "custominput",
   }

表单处理任务处理从先前输入任务提交的表单。注册类似于输入任务,除了函数本身应该接受一个可选的postkwarg。表单处理任务应该注册url_path,并重定向回输入任务(通过设置current_mode响应)。

自定义自动任务

在非常高级的用例中,可能需要根据许多因素动态生成任务列表。在这种情况下,可以定义一个完全自定义的自动任务:

@data_wizard.wizard_task(label="Custom Workflow", url_path="customauto", use_async=True)
def custom_auto(run):
    task_list = somehow_determine_tasks(run)
    return run.run_all(task_list)

注册与其他任务类似,加了use_async关键字,方便通过配置的任务后端进行后台处理。

一般来说,自动化任务列表中的任务应该是检查任务或其他自动任务。输入和表单处理任务应在自动化流程之外执行。

任务后端

可以通过BACKEND设置配置以下任何后端:

# myproject/settings.py

DATA_WIZARD = {
   "BACKEND": "data_wizard.backends.threading"  # Default
              "data_wizard.backends.immediate"
              "data_wizard.backends.celery"
}

data_wizard.backends.threading

threading后端为长时间运行的异步任务(即autodata)创建一个单独的线程。线程后端利用 Django 缓存将结果传递回状态 API。这是默认后端,但明确设置它仍然是一个好主意。

data_wizard.backends.immediate

后端在将immediate结果返回给客户端之前完成所有处理,即使对于其他“异步”任务(autodata)也是如此。此后端适用于小型电子表格,或用于解决线程问题。此后端保持最小状态,不建议用于涉及大型电子表格或多个同时导入过程的用例。

data_wizard.backends.celery

celery后端利用Celery处理异步任务,通常与Redis一起用作内存存储。默认情况下,这些附加依赖项不会随 Django 数据向导一起安装。如果要