V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
oddcc
V2EX  ›  Python

常用 Django 的同学看过来, 个人开源的小工具更新啦

  •  
  •   oddcc · 2017-05-23 13:33:30 +08:00 · 3316 次点击
    这是一个创建于 2520 天前的主题,其中的信息可能已经有所发展或是发生改变。

    书接上文个人第一个开源小项目, 希望能给大家带来方便

    • 此次更新了中文文档...
    • 增加了 FBV 的调用方式
    • 支持 Many-to-Many, Many-to-One, One-to-Many 的关系导出
    • 支持了 extra 和 annotate 的复杂查询

    可用性比之前上了一个台阶, 欢迎大家使用, 也欢迎提意见和建议, 谢谢!

    项目地址: https://github.com/oddcc/django-export-csv

    =======================================================

    django-export-csv

    Introduction

    Django 的一个 CSV 导出工具 可以很方便的把 queryset 导出为 CSV 文件, 为了避免导出文件过大, 占用服务器内存, 生成的是 StreamingHttpResponset.

    支持通过下面几种方式对导出的 CSV 文件进行定制

    1. 文件名
    2. 导出的时候文件名加 /不加时间戳
    3. 表头是不是使用 verbose_name
    4. 可以排除不想导出的字段
    5. 自定义导出字段的顺序
    6. 自定义表头
    7. 自定义字段的表现形式(serializer)
    8. 支持导出外键, 多对多, 外键反向查询这些关系, 需要自定义

    install

    Run:

    pip install django-export-csv
    

    Support Python 2.7 and 3.5, Django >= 1.8.

    usage

    使用 CBV 的话, 视图类需要继承ListView(或MultipleObjectMixin的子类)和QueryCsvMixin, 继承之后就可以调用render_csv_response方法把 queryset 导出为 CSV 文件, render_csv_response方法需要一个QuerySetValuesQuerySet的实例作为参数:

    使用 CBV

    from django_export_csv import QueryCsvMixin
    from django.views.generic.list import ListView
    
    from .models import Student
    
    
    class StudentListView(QueryCsvMixin, ListView):
        queryset = Student.objects.all()
    
        def get(self, *args, **kwargs):
            return self.render_csv_response(queryset)
    

    使用 FBV

    from django_export_csv import render_csv_response
    
    
    def student_list_view(request):
        if request.method == 'GET':
            queryset = Student.objects.all()
            return render_csv_response(queryset)
    

    定制 CSV

    视图类继承了 QueryCsvMixin之后, 就可以使用以下参数自定义 CSV 文件:

    1. filename - (default: None), 是个字符串, 如果不定义, CSV 会根据 model 来生成文件名.
    2. add_datestamp - (default: False), 是个布尔值, 如果为 True 的话, 导出的文件名末尾会添加当前时间的时间戳.
    3. use_verbose_names - (default: True), 是个布尔值, 如果设为 True, CSV 表头的名称会使用 model 中定义的 verbose_name.
    4. exclude_field - (default: []), 是个包含了不想导出的字段名的列表, 不设的话, 默认导出所有字段.
    5. field_order - (default: []), 是个列表, 可以把想定义排序的字段名写在里面, 导出的 CSV 会优先按顺序排列这个参数指定的字段, 再排剩下的字段.
    6. field_header_map - (default: {}), 是个字典, 用于自定义表头, key 应该是字段名, value 是表头中显示的内容, 这个参数的优先级比 verbose_name 高.
    7. field_serializer_map - (default: {}), 是个字典, 用于自定义 serializer, key 是字段名, value 是对应的函数名, 这个函数应该接收一个值并返回相应的内容.
    8. extra_field - (default: []), 是个列表, 用于定义不在数据库表中但又与 model 相关的字段, 比如外键的反向查询, 多对多关系等等, 也可以用于定义任意其他跟 model 相关的字段. 注意如果指定了extra_field参数, field_serializer_map中必须有相应的 serializer 配合才能工作.

    e.g:

    # data_init.py
    
    import datetime
    from .models import Student, College
    
    
    def create_student_and_get_queryset():
        college1, _ = College.objects.get_or_create(name="College 1st")
        college2, _ = College.objects.get_or_create(name="College 2nd")
    
        Student.objects.get_or_create(
            name='Jim', age=18, is_graduated=False, birthday=datetime.date(1998,6,6), college=college1
        )
        Student.objects.get_or_create(
            name='Bing', age=22, is_graduated=True, birthday=datetime.date(1994, 2, 6), college=college1
        )
        Student.objects.get_or_create(
            name='Monica', age=25, is_graduated=True, birthday=datetime.date(1991, 2, 6), college=college2
        )
    
        return Student.objects.all()
    
    
    # views.py
    
    from django_export_csv import QueryCsvMixin
    from django_export_csv import render_csv_response
    from django.views.generic.list import ListView
    
    from .models import Student
    from .data_init import create_student_and_get_queryset
    
    
    def boolean_serializer(value):
        if value == True:
            return 'Y'
        else:
            return 'N'
            
            
    def college_serializer(obj):
        return obj.college.name
    
    
    # CBV
    
    class StudentListView(QueryCsvMixin, ListView):
        filename = 'export_student_list'
        add_datestamp = True
        use_verbose_names = True
        exclude_field = ['id']
        field_order = ['name', 'is_graduated']
        field_header_map = {'is_graduated': 'Graduated'}
        field_serializer_map = {'is_graduated': boolean_serializer, 'college': college_serializer}
        queryset = Student.objects.all()
        extra_field = ['college']
    
        def get(self, *args, **kwargs):
            queryset = create_student_and_get_queryset()
            return self.render_csv_response(queryset)
            
    
    # FBV
    
    def student_list_view(request):
        filename = 'export_student_list'
        add_datestamp = True
        use_verbose_names = True
        exclude_field = ['id']
        field_order = ['name', 'is_graduated']
        field_header_map = {'is_graduated': 'Graduated'}
        field_serializer_map = {'is_graduated': boolean_serializer, 'college': college_serializer}
        extra_field = ['college']
    
        if request.method == 'GET':
            queryset = create_student_and_get_queryset()
            return render_csv_response(
                queryset, filename=filename, add_datestamp=add_datestamp, use_verbose_names=use_verbose_names,
                exclude_field=exclude_field, field_order=field_order, field_header_map=field_header_map,
                field_serializer_map=field_serializer_map, extra_field=extra_field
            )
    
    8 条回复    2017-05-26 11:55:50 +08:00
    corningsun
        1
    corningsun  
       2017-05-23 14:01:15 +08:00
    不错不错

    最近有个需求,也是需要导出数据。不过不是直接导出固定的表和字段,render_csv_response 方法能不能接收一个非 queryset 对象?
    oddcc
        2
    oddcc  
    OP
       2017-05-23 14:12:58 +08:00
    @corningsun 目前不能..
    prasanta
        3
    prasanta  
       2017-05-23 14:31:07 +08:00
    请问在什么情况下我会使用这个呢
    oddcc
        4
    oddcc  
    OP
       2017-05-23 15:34:30 +08:00
    @prasanta 各种管理系统中会用的多一点吧, 主要是公司里很多类似的导出需求, 用这个就方便多了
    clampist
        5
    clampist  
       2017-05-23 19:05:40 +08:00 via iPhone
    感谢分享,很实用啊
    uhayate
        6
    uhayate  
       2017-05-24 09:38:23 +08:00 via iPhone   ❤️ 1
    东西不错,不过看到介绍还是有点懵逼。能写一下应用场景这样最好,举几个例子,这样大家可能更了解它。
    oddcc
        7
    oddcc  
    OP
       2017-05-24 10:39:58 +08:00
    @uhayate 谢谢建议, 确实介绍中应该包括应用场景..楼上的同学也是提到这一点
    lovesecho
        8
    lovesecho  
       2017-05-26 11:55:50 +08:00
    django-import-export==0.5.1 目前在用这个,数据不大的话貌似也还凑合。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3359 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:38 · PVG 20:38 · LAX 05:38 · JFK 08:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.