ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

netbox 导出 csv 中文乱码、时区修改

2022-01-18 23:04:19  阅读:338  来源: 互联网

标签:netbox self 乱码 export table csv response columns


NetBox是IP地址管理(IPAM)和数据中心基础结构管理(DCIM)工具。 NetBox最初是由的网络工程团队构想的,它是专门为满足网络和基础架构工程师的需求而开发的。

项目地址:https://github.com/netbox-community/netbox


Netbox CSV 导出中文乱码

解决办法

修改文件:./netbox/netbox/netbox/views/generic.py

修改内容:

# 1. 在 import 语句后面添加一个新的类,重写父类 `TableExport`
...
class TableExport2(TableExport):
    def response(self, filename=None):
        response = HttpResponse(content_type="text/csv; charset=utf-8-sig")
        if filename is not None:
            response["Content-Disposition"] = 'attachment; filename="{}"'.format(filename)
        response.write(self.export())
        return response

# 2. 修改 export_table 方法(大约在文件 200 行左右)让其使用重写的类来实例化
class ObjectListView(ObjectPermissionRequiredMixin, View):
    ...
    # 
    def export_table(self, table, columns=None):
        ...
        exporter = TableExport2(
            export_format=TableExport.CSV,
            table=table,
            exclude_columns=exclude_columns
        )
        ...

修改文件后,重启 netbox 服务。如果是容器部署,重启 netbox-docker_netbox_1 容器(暴露端口的那个容器)。

解决过程记录

Django 导出 csv 文件乱码,一般是编码格式的问题,可以参考:解决 Django 导出 csv 乱码问题,根据这篇文章,思路就是只需要修改 HttpResponsecharset 就行了。

在 url.py 中搜索 export 相关字样,发现没有相关路由。

在从 export 的 html 中可以看到,它是直接把 export 传给了后端。

<li><a class="dropdown-item" href="?{% if url_params %}{{ url_params.urlencode }}&{% endif %}export">All 

后端处理的时候肯定是需要解析这个字段的,在 views.py 中搜索,发现定义了 export 的按钮,是继承自 generic.ObjectListView 的,所以这个方法应该是定义在 generic.ObjectListView 中。

class ConsolePortListView(generic.ObjectListView):
    queryset = ConsolePort.objects.all()
    filterset = filtersets.ConsolePortFilterSet
    filterset_form = forms.ConsolePortFilterForm
    table = tables.ConsolePortTable
    action_buttons = ('import', 'export')

在 generic 中找到如下方法,证明前端 export 传过来的参数是由 export_table 来处理:

       ...
        if 'export' in request.GET:

            # Export the current table view
            if request.GET['export'] == 'table':
                table = self.get_table(request, permissions)
                columns = [name for name, _ in table.selected_columns]
                return self.export_table(table, columns)
    ...
    def export_table(self, table, columns=None):
        """
        Export all table data in CSV format.

        :param table: The Table instance to export
        :param columns: A list of specific columns to include. If not specified, all columns will be exported.
        """
        exclude_columns = {'pk'}
        if columns:
            all_columns = [col_name for col_name, _ in table.selected_columns + table.available_columns]
            exclude_columns.update({
                col for col in all_columns if col not in columns
            })
        exporter = TableExport(
            export_format=TableExport.CSV,
            table=table,
            exclude_columns=exclude_columns
        )
        return exporter.response(
            filename=f'netbox_{self.queryset.model._meta.verbose_name_plural}.csv'
        )

可以看到这个方法返回了一个 response 对象,修改这个对象的 charset:

    def export_table(self, table, columns=None):
        ...
        response = exporter.response(
            filename=f'netbox_{self.queryset.model._meta.verbose_name_plural}.csv'
        )
        response.charset = "utf-8-sig"
        return response

修改之后,发现前端页面中,确实增加了 charset 且值正确,但是导出的文件仍为乱码。

分析 exporter.response 这个对象——来自于 django-tables2 插件,初始化 TableExport 时里面使用了 export_format=TableExport.CSV,这里指定了 csv 格式

    exporter = TableExport(
        export_format=TableExport.CSV,
        table=table,
        exclude_columns=exclude_columns
    )
 

之后调用了这个类的 response 方法:

    def response(self, filename=None):
        response = HttpResponse(content_type=self.content_type())
        if filename is not None:
            response["Content-Disposition"] = 'attachment; filename="{}"'.format(filename)

        response.write(self.export())
        return 

通过分析这个类,发现这里 self.content_type() 调用的是传入的 self.format,即 export_format=TableExport.CSV 值为 ‘csv’。
由于这个值会被 tablib 这个库调用(类中的 self.export()方法调用),所以不能重写这个字段来实现。

response 方法也不支持传参,所以这里的 csv 编码格式是写死的,即:"text/csv; charset=utf-8"

而且 response.write(self.export()) 写入对象时已经是 utf-8 了,写入完成之后再修改编码也没有任何意义。

最后思考的结果是:在 netbox 的 generic.py 中重写 def response(self, filename=None): 方法,固定其编码为 utf-8-sig

因为 netbox 的导出只使用了 csv 格式,所以把编码格式固定不会对 netbox 运行造成影响,只是修改了导出的格式。

最终解决方法见上方。

Netbox 时区不对

修改文件: ./netbox-docker/configuration/extra.py

标签:netbox,self,乱码,export,table,csv,response,columns
来源: https://blog.csdn.net/q965844841qq/article/details/122570724

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有