zoukankan      html  css  js  c++  java
  • Python Django 零基础破门而入篇(二)

    本文介绍如何使用django-import-export 实现以下功能点

    官方实例:https://django-import-export.readthedocs.io/en/latest/getting_started.html#creating-import-export-resource

    1.导入 导出

    2.批量更新

    3.如何导出model中 ForeignKey 字段的其它的属性值

     项目github地址:https://github.com/wangcongxing/OpenTheDoor

    如何新建django项目请参照

    Python Django 零基础破门而入篇(一)

    1.安装 django-import-export

    pip install django-import-export

    2.配置项目文件下 settings.py

    修改 INSTALLED_APPS

    默认值为False。它确定库是否会在数据导入中使用数据库事务,以确保安全

    新增 IMPORT_EXPORT_USE_TRANSACTIONS = True

    3.修改app-->admin.py 设置导出代码列头 代码如下

    from django.contrib import admin
    from app import models
    from import_export import resources
    from import_export.admin import ImportExportModelAdmin
    from django.apps import apps
    
    # Register your models here.
    admin.site.site_header = "大佬管理"
    admin.site.site_title = "大佬管理后台管理"
    
    
    class bossInfoResource(resources.ModelResource):
        def __init__(self):
            super(bossInfoResource, self).__init__()
    
            field_list = models.bossInfo._meta.fields
            self.vname_dict = {}
            for i in field_list:
                self.vname_dict[i.name] = i.verbose_name
    
        # 默认导入导出field的column_name为字段的名称,这里修改为字段的verbose_name
        def get_export_fields(self):
            fields = self.get_fields()
            for field in fields:
                field_name = self.get_field_name(field)
                # 如果我们设置过verbose_name,则将column_name替换为verbose_name。否则维持原有的字段名
                if field_name in self.vname_dict.keys():
                    field.column_name = self.vname_dict[field_name]
            return fields
    
        def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
            print("after_import")
    
        def after_import_instance(self, instance, new, **kwargs):
            print("after_import_instance")
    
        class Meta:
            model = models.bossInfo
            skip_unchanged = True
            report_skipped = True
            fields = (
            "id", "age", "gender", "likeFruit", "userUrl", "name", "desc", "createTime", "lastTime", "creator", "editor")
    
    
    @admin.register(models.bossInfo)
    class bossInfoAdmin(ImportExportModelAdmin):
        fields = (
            "name", "age", "gender",
            "likeFruit", "userUrl", "desc")
        list_display = (
            "name", "age", "gender",
            "likeFruit", "userUrl",
            "createTime",
            "lastTime",
            "creator", "editor")
        list_display_links = ("name",)
        exclude = ("createTime", "creator", "editor")
        search_fields = ("name",)
        list_filter = ("gender", "likeFruit")
        model_icon = "fa fa-tag"
        list_per_page = 20
        ordering = ["-id"]
        resource_class = bossInfoResource
    
        def save_model(self, request, obj, form, change):
            if form.is_valid():
                if change:
                    obj.editor = request.user
                else:
                    obj.creator = request.user
                    obj.editor = request.user
                    obj.save()
            super().save_model(request, obj, form, change)

     4.运行效果

    5.导出excel 存在以下问题

    1.创建者 / 修改者 如何显示用户名

    2.创建时间 / 修改时间如何进行格式化

    3.继续修改admin.py  重写导出 export 完整代码如下

    from django.contrib import admin
    from app import models
    from import_export import resources
    from import_export.admin import ImportExportModelAdmin
    from django.apps import apps
    from django.db.models import QuerySet
    import tablib
    # Register your models here.
    admin.site.site_header = "大佬管理"
    admin.site.site_title = "大佬管理后台管理"
    
    
    class bossInfoResource(resources.ModelResource):
        def __init__(self):
            super(bossInfoResource, self).__init__()
    
            field_list = models.bossInfo._meta.fields
            self.vname_dict = {}
            self.fkey = []
            for i in field_list:
                self.vname_dict[i.name] = i.verbose_name
                self.fkey.append(i.name)
    
        # 默认导入导出field的column_name为字段的名称,这里修改为字段的verbose_name
        def get_export_fields(self):
            fields = self.get_fields()
            for field in fields:
                field_name = self.get_field_name(field)
                # 如果我们设置过verbose_name,则将column_name替换为verbose_name。否则维持原有的字段名
                if field_name in self.vname_dict.keys():
                    field.column_name = self.vname_dict[field_name]
            return fields
    
        def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
            print("after_import")
    
        def after_import_instance(self, instance, new, **kwargs):
            print("after_import_instance")
    
        # 重载resources.py的export方法,修改将要导出的data的某些外键相关数据。默认导出外键id,这里修改为导出外键对应的值
        def export(self, queryset=None, *args, **kwargs):
            self.before_export(queryset, *args, **kwargs)
            if queryset is None:
                queryset = self.get_queryset()
            headers = self.get_export_headers()
            data = tablib.Dataset(headers=headers)
            # 获取所有外键名称在headers中的位置
            fk_index = {}
            for fk in self.fkey:
                fk_index[fk] = headers.index(self.vname_dict[fk])
            # --------------------- #
    
            if isinstance(queryset, QuerySet):
                # Iterate without the queryset cache, to avoid wasting memory when
                # exporting large datasets.
                iterable = queryset.iterator()
            else:
                iterable = queryset
            for obj in iterable:
                # --------------------- #
                # 获取将要导出的源数据,这里export_resource返回的是列表,便于更改。替换到外键的值
                # 可以对所有字段值进行二次处理
                res = self.export_resource(obj)
                res[fk_index['id']] = obj.id
                res[fk_index['age']] = obj.age
                res[fk_index['gender']] = obj.gender
                res[fk_index['likeFruit']] = obj.likeFruit
                res[fk_index['userUrl']] = obj.userUrl
                res[fk_index['name']] = obj.name
                res[fk_index['desc']] = obj.desc
                res[fk_index['createTime']] = obj.createTime
                res[fk_index['lastTime']] = obj.lastTime
                res[fk_index['creator']] = obj.creator.username
                res[fk_index['editor']] = obj.editor.username
                data.append(res)
                # --------------------- #
            self.after_export(queryset, data, *args, **kwargs)
            return data
    
        class Meta:
            model = models.bossInfo
            skip_unchanged = True
            report_skipped = True
            fields = (
                "id", "age", "gender", "likeFruit", "userUrl", "name", "desc", "createTime", "lastTime", "creator",
                "editor")
    
    
    @admin.register(models.bossInfo)
    class bossInfoAdmin(ImportExportModelAdmin):
        fields = (
            "name", "age", "gender",
            "likeFruit", "userUrl", "desc")
        list_display = (
            "name", "age", "gender",
            "likeFruit", "userUrl",
            "createTime",
            "lastTime",
            "creator", "editor")
        list_display_links = ("name",)
        exclude = ("createTime", "creator", "editor")
        search_fields = ("name",)
        list_filter = ("gender", "likeFruit")
        model_icon = "fa fa-tag"
        list_per_page = 20
        ordering = ["-id"]
        resource_class = bossInfoResource
    
        def save_model(self, request, obj, form, change):
            if form.is_valid():
                if change:
                    obj.editor = request.user
                else:
                    obj.creator = request.user
                    obj.editor = request.user
                    obj.save()
            super().save_model(request, obj, form, change)

     

     最终导出效果

    6.导入配置

    点击导入

    提示都是字段名,用户肯定整不明白的

    赶紧改成中文的   解决方法  

    通过重写导入页面

     

    7.在应用目录(app)下-->templatetags-->apptags.py

    8.修改项目settings.py

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')]
            ,
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
                'libraries': {
                    'apptags': 'app.templatetags.apptags'
                },
            },
        },
    ]

    9.重写django-import-export 导入页面

    在项目templates下新建 admin-->import_export--> import.html 

    import.html代码如下  将{{ fields|join:", " }}  替换成 apptags.py 定义的 import_head_tag 方法即可

    找到项目中import_export 文件夹中 

    10.在项目中的templates-->admin-->import_export 下把导入导出两个页面都复制过来(export.html   import.html)

    11.修改import.html  标注背景色的两处

    {% extends "admin/import_export/base.html" %}
    {% load static simpletags apptags %}
    {% load i18n %}
    {% load admin_urls %}
    {% load import_export_tags %}
    {% load static %}
    
    {% block extrastyle %}{{ block.super }}
        <link rel="stylesheet" type="text/css" href="{% static "import_export/import.css" %}"/>{% endblock %}
    
    {% block breadcrumbs_last %}
        {% trans "Import" %}
    {% endblock %}
    
    {% block content %}
    
        {% if confirm_form %}
            <form action="{% url opts|admin_urlname:"process_import" %}" method="POST">
                {% csrf_token %}
                {{ confirm_form.as_p }}
                <p>
                    {% trans "Below is a preview of data to be imported. If you are satisfied with the results, click 'Confirm import'" %}
                </p>
                <div class="submit-row">
                    <input type="submit" class="default" name="confirm" value="{% trans "Confirm import" %}">
                </div>
            </form>
        {% else %}
            <form action="" method="post" enctype="multipart/form-data">
                {% csrf_token %}
    
                <p>
                    {% trans "This importer will import the following fields: " %}
                    {# <code>{{ fields|join:", " }}</code> #}
                    <code>{% import_head_tag %}</code>
                </p>
    
                <fieldset class="module aligned">
                    {% for field in form %}
                        <div class="form-row">
                            {{ field.errors }}
    
                            {{ field.label_tag }}
    
                            {{ field }}
    
                            {% if field.field.help_text %}
                                <p class="help">{{ field.field.help_text|safe }}</p>
                            {% endif %}
                        </div>
                    {% endfor %}
                </fieldset>
    
                <div class="submit-row">
                    <input type="submit" class="default" value="{% trans "Submit" %}">
                </div>
            </form>
        {% endif %}
    
        {% if result %}
    
            {% if result.has_errors %}
    
                <h2>{% trans "Errors" %}</h2>
                <ul>
                    {% for error in result.base_errors %}
                        <li>
                            {{ error.error }}
                            <div class="traceback">{{ error.traceback|linebreaks }}</div>
                        </li>
                    {% endfor %}
                    {% for line, errors in result.row_errors %}
                        {% for error in errors %}
                            <li>
                                {% trans "Line number" %}: {{ line }} - {{ error.error }}
                                <div><code>{{ error.row.values|join:", " }}</code></div>
                                <div class="traceback">{{ error.traceback|linebreaks }}</div>
                            </li>
                        {% endfor %}
                    {% endfor %}
                </ul>
    
            {% elif result.has_validation_errors %}
    
                <h2>{% trans "Some rows failed to validate" %}</h2>
    
                <p>{% trans "Please correct these errors in your data where possible, then reupload it using the form above." %}</p>
    
                <table class="import-preview">
                    <thead>
                    <tr>
                        <th>{% trans "Row" %}</th>
                        <th>{% trans "Errors" %}</th>
                        {% for field in result.diff_headers %}
                            <th>{{ field }}</th>
                        {% endfor %}
                    </tr>
                    </thead>
                    <tbody>
                    {% for row in result.invalid_rows %}
                        <tr>
                            <td>{{ row.number }} </td>
                            <td class="errors">
                                <span class="validation-error-count">{{ row.error_count }}</span>
                                <div class="validation-error-container">
                                    <ul class="validation-error-list">
                                        {% for field_name, error_list in row.field_specific_errors.items %}
                                            <li>
                                                <span class="validation-error-field-label">{{ field_name }}</span>
                                                <ul>
                                                    {% for error in error_list %}
                                                        <li>{{ error }}</li>
                                                    {% endfor %}
                                                </ul>
                                            </li>
                                        {% endfor %}
                                        {% if row.non_field_specific_errors %}
                                            <li>
                                                <span class="validation-error-field-label">{% trans "Non field specific" %}</span>
                                                <ul>
                                                    {% for error in row.non_field_specific_errors %}
                                                        <li>{{ error }}</li>
                                                    {% endfor %}
                                                </ul>
                                            </li>
                                        {% endif %}
                                    </ul>
                                </div>
                            </td>
                            {% for field in row.values %}
                                <td>{{ field }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
    
            {% else %}
    
                <h2>{% trans "Preview" %}</h2>
    
                <table class="import-preview">
                    <thead>
                    <tr>
                        <th></th>
                        {% for field in result.diff_headers %}
                            <th>{{ field }}</th>
                        {% endfor %}
                    </tr>
                    </thead>
                    {% for row in result.valid_rows %}
                        <tr class="{{ row.import_type }}">
                            <td class="import-type">
                                {% if row.import_type == 'new' %}
                                    {% trans "New" %}
                                {% elif row.import_type == 'skip' %}
                                    {% trans "Skipped" %}
                                {% elif row.import_type == 'delete' %}
                                    {% trans "Delete" %}
                                {% elif row.import_type == 'update' %}
                                    {% trans "Update" %}
                                {% endif %}
                            </td>
                            {% for field in row.diff %}
                                <td>{{ field }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                </table>
    
            {% endif %}
    
        {% endif %}
    {% endblock %}

    12.运行效果

    导出包含创建时间,修改时间,创建者,修改者

    导入 创建者修改者自动复制  选项值需要特殊处理例如多选

    13.自动将当前登录用户 赋值每条导入对象(instance)的 创建者/修改者字段  

    导入效果

    14.最终admin.py代码

    import traceback
    from copy import deepcopy
    
    from django.contrib import admin
    from django.core.exceptions import ValidationError
    from django.db.transaction import TransactionManagementError
    from django.utils.encoding import force_text
    from import_export.results import RowResult
    
    from app import models
    from import_export import resources
    from import_export.admin import ImportExportModelAdmin
    from django.apps import apps
    from django.db.models import QuerySet
    import tablib
    
    # Register your models here.
    admin.site.site_header = "大佬管理"
    admin.site.site_title = "大佬管理后台管理"
    
    
    class bossInfoResource(resources.ModelResource):
    
        def __init__(self):
            super(bossInfoResource, self).__init__()
    
            field_list = models.bossInfo._meta.fields
            self.vname_dict = {}
            self.fkey = []
            customeFields = (
                "id", "age", "gender", "likeFruit", "userUrl", "name", "desc",)
            for i in field_list:
                if i.name in customeFields:
                    self.vname_dict[i.name] = i.verbose_name.lower()
                    self.fkey.append(i.name)
    
        # 默认导入导出field的column_name为字段的名称,这里修改为字段的verbose_name
        def get_export_fields(self):
            fields = self.get_fields()
            for field in fields:
                field_name = self.get_field_name(field)
                # 如果我们设置过verbose_name,则将column_name替换为verbose_name。否则维持原有的字段名
                if field_name in self.vname_dict.keys():
                    field.column_name = self.vname_dict[field_name]
            return fields
    
        def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
            print("after_import")
    
        def after_import_instance(self, instance, new, **kwargs):
            print("after_import_instance")
    
        # 重载resources.py的export方法,修改将要导出的data的某些外键相关数据。默认导出外键id,这里修改为导出外键对应的值
        def export(self, queryset=None, *args, **kwargs):
            self.before_export(queryset, *args, **kwargs)
            if queryset is None:
                queryset = self.get_queryset()
            headers = self.get_export_headers()
            headers.append("创建时间")
            headers.append("修改时间")
            headers.append("创建者")
            headers.append("修改者")
            data = tablib.Dataset(headers=headers)
            # 获取所有外键名称在headers中的位置
            fk_index = {}
            for fk in self.fkey:
                fk_index[fk] = headers.index(self.vname_dict[fk])
            # --------------------- #
    
            if isinstance(queryset, QuerySet):
                # Iterate without the queryset cache, to avoid wasting memory when
                # exporting large datasets.
                iterable = queryset.iterator()
            else:
                iterable = queryset
            for obj in iterable:
                # --------------------- #
                # 获取将要导出的源数据,这里export_resource返回的是列表,便于更改。替换到外键的值
                # 可以对所有字段值进行二次处理
                res = self.export_resource(obj)
                res[fk_index['id']] = obj.id
                res[fk_index['age']] = obj.age
                res[fk_index['gender']] = obj.gender
                res[fk_index['likeFruit']] = obj.likeFruit
                res[fk_index['userUrl']] = obj.userUrl
                res[fk_index['name']] = obj.name
                res[fk_index['desc']] = obj.desc
                res.append(obj.createTime)
                res.append(obj.lastTime)
                res.append(obj.creator.username)
                res.append(obj.editor.username)
                data.append(res)
                # --------------------- #
            self.after_export(queryset, data, *args, **kwargs)
            return data
    
        # 导入前
        def before_import_row(self, row, **kwargs):
            print(row)
    
        # 导入后(执行更新创建者修改)
        def after_import_row(self, row, row_result, **kwargs):
            print(row)
    
        # 导入数据 自动将当前登录用户 赋值给创建者和修改者
        def import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs):
            print(instance_loader)
            row_result = self.get_row_result_class()()
            try:
                self.before_import_row(row, **kwargs)
                instance, new = self.get_or_init_instance(instance_loader, row)
                self.after_import_instance(instance, new, **kwargs)
                if new:
                    row_result.import_type = RowResult.IMPORT_TYPE_NEW
                else:
                    row_result.import_type = RowResult.IMPORT_TYPE_UPDATE
                row_result.new_record = new
                original = deepcopy(instance)
                diff = self.get_diff_class()(self, original, new)
                if self.for_delete(row, instance):
                    if new:
                        row_result.import_type = RowResult.IMPORT_TYPE_SKIP
                        diff.compare_with(self, None, dry_run)
                    else:
                        row_result.import_type = RowResult.IMPORT_TYPE_DELETE
                        self.delete_instance(instance, using_transactions, dry_run)
                        diff.compare_with(self, None, dry_run)
                else:
                    import_validation_errors = {}
                    try:
                        self.import_obj(instance, row, dry_run)
                    except ValidationError as e:
                        # Validation errors from import_obj() are passed on to
                        # validate_instance(), where they can be combined with model
                        # instance validation errors if necessary
                        import_validation_errors = e.update_error_dict(import_validation_errors)
                    if self.skip_row(instance, original):
                        row_result.import_type = RowResult.IMPORT_TYPE_SKIP
                    else:
                        self.validate_instance(instance, import_validation_errors)
                        print(instance)
                        print("dry_run", dry_run)
                        if instance.creator is None:
                            instance.creator = kwargs["user"]
                        instance.editor = kwargs["user"]
                        self.save_instance(instance, using_transactions, dry_run)
                        self.save_m2m(instance, row, using_transactions, dry_run)
                        # Add object info to RowResult for LogEntry
                        row_result.object_id = instance.pk
                        row_result.object_repr = force_text(instance)
                    diff.compare_with(self, instance, dry_run)
    
                row_result.diff = diff.as_html()
                self.after_import_row(row, row_result, **kwargs)
    
            except ValidationError as e:
                row_result.import_type = RowResult.IMPORT_TYPE_INVALID
                row_result.validation_error = e
            except Exception as e:
                row_result.import_type = RowResult.IMPORT_TYPE_ERROR
                # There is no point logging a transaction error for each row
                # when only the original error is likely to be relevant
                if not isinstance(e, TransactionManagementError):
                    print(e)
                tb_info = traceback.format_exc()
                row_result.errors.append(self.get_error_result_class()(e, tb_info, row))
            return row_result
    
        class Meta:
            model = models.bossInfo
            skip_unchanged = True
            report_skipped = True
            fields = (
                "id", "age", "gender", "likeFruit", "userUrl", "name", "desc",)
    
    
    @admin.register(models.bossInfo)
    class bossInfoAdmin(ImportExportModelAdmin):
        fields = (
            "name", "age", "gender",
            "likeFruit", "userUrl", "desc")
        list_display = (
            "name", "age", "gender",
            "likeFruit", "userUrl",
            "createTime",
            "lastTime",
            "creator", "editor")
        list_display_links = ("name",)
        exclude = ("createTime", "creator", "editor")
        search_fields = ("name",)
        list_filter = ("gender", "likeFruit")
        model_icon = "fa fa-tag"
        list_per_page = 20
        ordering = ["-id"]
        resource_class = bossInfoResource
    
        def save_model(self, request, obj, form, change):
            if form.is_valid():
                if change:
                    obj.editor = request.user
                else:
                    obj.creator = request.user
                    obj.editor = request.user
                    obj.save()
            super().save_model(request, obj, form, change)

    15.给导入导出页面 (export.html    import.html) 新增返回按钮

    {% extends "admin/import_export/base.html" %}
    {% load static simpletags apptags %}
    {% load i18n %}
    {% load admin_urls %}
    {% load import_export_tags %}
    {% load static %}
    
    {% block extrastyle %}{{ block.super }}
        <link rel="stylesheet" type="text/css" href="{% static "import_export/import.css" %}"/>{% endblock %}
    
    {% block breadcrumbs_last %}
        {% trans "Import" %}
    {% endblock %}
    
    {% block content %}
    
        {% if confirm_form %}
            <form action="{% url opts|admin_urlname:"process_import" %}" method="POST">
                {% csrf_token %}
                {{ confirm_form.as_p }}
                <p>
                    {% trans "Below is a preview of data to be imported. If you are satisfied with the results, click 'Confirm import'" %}
                </p>
                <div class="submit-row">
                    <input type="submit" class="default" name="confirm" value="{% trans "Confirm import" %}">
                </div>
            </form>
        {% else %}
            <form action="" method="post" enctype="multipart/form-data">
                {% csrf_token %}
    
                <p>
                    {% trans "This importer will import the following fields: " %}
                    {# <code>{{ fields|join:", " }}</code> #}
                    <code>{% import_head_tag %}</code>
                </p>
    
                <fieldset class="module aligned">
                    {% for field in form %}
                        <div class="form-row">
                            {{ field.errors }}
    
                            {{ field.label_tag }}
    
                            {{ field }}
    
                            {% if field.field.help_text %}
                                <p class="help">{{ field.field.help_text|safe }}</p>
                            {% endif %}
                        </div>
                    {% endfor %}
                </fieldset>
    
                <div class="submit-row">
                    <input type="button" class="el-button el-button--default is-plain" style="float: left"
                           onclick="javascript:window.history.go(-1)" value="返回"/>
                    <input type="submit" class="default" value="{% trans "Submit" %}">
                </div>
            </form>
        {% endif %}
    
        {% if result %}
    
            {% if result.has_errors %}
    
                <h2>{% trans "Errors" %}</h2>
                <ul>
                    {% for error in result.base_errors %}
                        <li>
                            {{ error.error }}
                            <div class="traceback">{{ error.traceback|linebreaks }}</div>
                        </li>
                    {% endfor %}
                    {% for line, errors in result.row_errors %}
                        {% for error in errors %}
                            <li>
                                {% trans "Line number" %}: {{ line }} - {{ error.error }}
                                <div><code>{{ error.row.values|join:", " }}</code></div>
                                <div class="traceback">{{ error.traceback|linebreaks }}</div>
                            </li>
                        {% endfor %}
                    {% endfor %}
                </ul>
    
            {% elif result.has_validation_errors %}
    
                <h2>{% trans "Some rows failed to validate" %}</h2>
    
                <p>{% trans "Please correct these errors in your data where possible, then reupload it using the form above." %}</p>
    
                <table class="import-preview">
                    <thead>
                    <tr>
                        <th>{% trans "Row" %}</th>
                        <th>{% trans "Errors" %}</th>
                        {% for field in result.diff_headers %}
                            <th>{{ field }}</th>
                        {% endfor %}
                    </tr>
                    </thead>
                    <tbody>
                    {% for row in result.invalid_rows %}
                        <tr>
                            <td>{{ row.number }} </td>
                            <td class="errors">
                                <span class="validation-error-count">{{ row.error_count }}</span>
                                <div class="validation-error-container">
                                    <ul class="validation-error-list">
                                        {% for field_name, error_list in row.field_specific_errors.items %}
                                            <li>
                                                <span class="validation-error-field-label">{{ field_name }}</span>
                                                <ul>
                                                    {% for error in error_list %}
                                                        <li>{{ error }}</li>
                                                    {% endfor %}
                                                </ul>
                                            </li>
                                        {% endfor %}
                                        {% if row.non_field_specific_errors %}
                                            <li>
                                                <span class="validation-error-field-label">{% trans "Non field specific" %}</span>
                                                <ul>
                                                    {% for error in row.non_field_specific_errors %}
                                                        <li>{{ error }}</li>
                                                    {% endfor %}
                                                </ul>
                                            </li>
                                        {% endif %}
                                    </ul>
                                </div>
                            </td>
                            {% for field in row.values %}
                                <td>{{ field }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
    
            {% else %}
    
                <h2>{% trans "Preview" %}</h2>
    
                <table class="import-preview">
                    <thead>
                    <tr>
                        <th></th>
                        {% for field in result.diff_headers %}
                            <th>{{ field }}</th>
                        {% endfor %}
                    </tr>
                    </thead>
                    {% for row in result.valid_rows %}
                        <tr class="{{ row.import_type }}">
                            <td class="import-type">
                                {% if row.import_type == 'new' %}
                                    {% trans "New" %}
                                {% elif row.import_type == 'skip' %}
                                    {% trans "Skipped" %}
                                {% elif row.import_type == 'delete' %}
                                    {% trans "Delete" %}
                                {% elif row.import_type == 'update' %}
                                    {% trans "Update" %}
                                {% endif %}
                            </td>
                            {% for field in row.diff %}
                                <td>{{ field }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                </table>
    
            {% endif %}
    
        {% endif %}
    {% endblock %}

    14.项目运行安装包版本

    需要留意tablib 库版本

  • 相关阅读:
    如何使 Postgresql 的psql 使用 中文提示信息
    Makfile中的 依赖关系
    防范计算机木马入侵反恶意联盟落户滨海 狼人:
    印度最大软件开发商塔塔咨询官网首页被黑 狼人:
    河北银行:用CDP保障业务系统的故障快速恢复 狼人:
    甲骨文11g数据库爆零日攻击 可完全攻破 狼人:
    Adobe Reader与IE 领衔漏洞榜 狼人:
    黑客藏毒于火狐插件 目标瞄准Windows系统 狼人:
    网络订票当心三类陷阱 最好当场识别真伪 狼人:
    微软基于云计算免费杀毒软件Morro曝光 狼人:
  • 原文地址:https://www.cnblogs.com/wangcongxing/p/13551889.html
Copyright © 2011-2022 走看看