20、Django导入导出功能

第一步:安装插件

pip install django-import-export

第二部:更新settings.py配置

INSTALLED_APPS = (
    ...
    'import_export',
)

第三部:在admin.py文件中写入如下代码

from django.contrib import admin
from .models import Article
from import_export.admin import ImportExportModelAdmin


# 自定义模型管理类
@admin.register(Article)
class ArticleAdmin(ImportExportModelAdmin):
    list_display = ("id", "title", "author", "content", "score", "pub_date", "update_date", "full_name")
    list_display_links = ("title", "content")
    list_per_page = 10
    list_filter = ("title", "author")
    search_fields = ("title", "content")

优化:

如果字段太多,只想导出一部分内容怎么办

from import_export import resources

class ArticleResource(resources.ModelResource):
    class Meta:
        model = Article
        #导出内容
        fields = ("id", "title", "author",)
        # 导出顺序
        export_order = ("id", "title", "author")

        
class ArticleAdmin(ImportExportModelAdmin):
    '''略'''
    resource_class = ArticleResource

导出的数据表头是英文,我想要中文 verbose_name 的备注

class ArticleResource(resources.ModelResource):
    # 默认导入导出field的column_name为字段的名称,这里修改为字段的verbose_name
    def __init__(self, input_contract=None):
        super(ArticleResource, self).__init__()
        field_list = Article._meta.fields
        self.verbose_name_dict = {}
        for i in field_list:
            self.verbose_name_dict[i.name] = i.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.verbose_name_dict.keys():
                field.column_name = self.verbose_name_dict[field_name]
        return fields
    
    class Meta:
        model = Article
        #导出内容
        fields = ("id", "title", "author",)
        # 导出顺序
        export_order = ("id", "title", "author")

例如

models.py

class Article(models.Model):
    """
    主题表/文章表
    """
    title = models.CharField(max_length=128, unique=True, verbose_name="标题", help_text="请填写标题")
    slug = models.SlugField(max_length=128, unique=True, verbose_name="url标识符")
    content = RichTextUploadingField(verbose_name="内容", config_name='awesome_ckeditor', )
    node = models.ForeignKey(Node, on_delete=models.DO_NOTHING, verbose_name="所属节点")
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="user_article", verbose_name="作者")
    source = models.ForeignKey(Source, on_delete=models.DO_NOTHING, verbose_name="来源", blank=True, null=True)
    tags = models.ManyToManyField(Tag, verbose_name="标签", related_name="tags_article", blank=True)
    num_views = models.IntegerField(default=0, verbose_name="浏览数量")
    num_favorites = models.IntegerField(default=0, verbose_name="收藏数量")
    last_answerer = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="last_answerer_article",
                                      verbose_name="最后回复者", blank=True,
                                      null=True)
    show_status = models.BooleanField(default=True, verbose_name="显示状态")
    time_create = models.DateTimeField(auto_now_add=True, verbose_name="发表时间")
    time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")

admins.py

from django.contrib import admin
from django.forms import widgets
from apps.blog.models import *
from apps.blog.forms import ArticleAdminForm
from django.contrib.admin import SimpleListFilter
from django.utils.html import format_html
from import_export import resources, fields
from import_export.admin import ImportExportModelAdmin
from import_export.admin import ImportExportActionModelAdmin
from import_export.admin import ExportActionMixin
from import_export.widgets import ForeignKeyWidget
from django.contrib.auth import get_user_model

User = get_user_model()


# https://github.com/django-import-export/django-import-export/issues/758
# Register your models here.

class ArticleResource(resources.ModelResource):
    # 外键可视化导出
    user = fields.Field(
        column_name='user',
        # user 在本模型外键的字段名称
        attribute='user',
        # username 外键的里面的字段名
        widget=ForeignKeyWidget(User, 'username'))

    last_answerer = fields.Field(
        column_name='last_answerer',
        attribute='last_answerer',
        widget=ForeignKeyWidget(User, 'username'))

    def __init__(self, input_contract=None):
        super(ArticleResource, self).__init__()
        field_list = Article._meta.fields
        self.verbose_name_dict = {}
        for i in field_list:
            self.verbose_name_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.verbose_name_dict.keys():
                field.column_name = self.verbose_name_dict[field_name]
        return fields

    class Meta:
        skip_unchanged = True  # 是否跳过的记录出现在导入结果对象
        report_skipped = True  # 所有记录将被导入
        # export_order = ('id', )
        model = Article


class ArticleAdmin(ImportExportActionModelAdmin):
    # change_list_template = "change_list_custom.html"  # 自定义的模板名称
    form = ArticleAdminForm  # 指定了表单,就不要再用 formfield_overrides 了

    def get_actions(self, request):
        # 列表禁用删除操作
        actions = super(ArticleAdmin, self).get_actions(request)
        if 'delete_selected' in actions and not request.user.is_superuser:
            del actions['delete_selected']
        return actions

    def has_add_permission(self, request, obj=None):
        # 编辑和列表页面非超管禁用 add 按钮
        if request.user.is_superuser:
            return True
        return False

    def show_status_button(self, obj):
        return format_html('<a href="{}" title="查看站点">{}</a>', obj.id, obj.show_status)

    show_status_button.short_description = "审核"

    def get_list_display(self, request):
        """
        Return a sequence containing the fields to be displayed on the
        changelist.
        """
        if request.user.is_superuser:
            list_display = ['id', 'thumb_shouw', 'title', 'node', 'num_views', 'show_status', 'slug', 'user',
                            'show_status_button', 'time_create']
            return list_display
        else:
            list_display = ['thumb_shouw', 'title', 'node', 'num_views', 'show_status', 'slug', 'user',
                            'show_status_button', ]
            return list_display

    # list_display = ['id', 'thumb_shouw', 'title', 'node', 'num_views', 'show_status', 'slug', 'user',
    #                 'show_status_button', 'time_create']

    list_display_links = ['id', 'thumb_shouw', 'title', 'node', 'num_views', 'user']
    list_filter = ['id', 'source__name', NodeFilter]
    search_fields = ['title_short', 'user', 'content']
    # list_editable = ["show_status", ]
    # style_fields = {"content": "ueditor"}
    readonly_fields = ('slug',)
    show_detail_fields = ['show_status', ]
    resource_class = ArticleResource


admin.site.register(Article, ArticleAdmin)

Last updated