Skip to content

Instantly share code, notes, and snippets.

@quxf2012
Last active November 22, 2023 10:09
Show Gist options
  • Save quxf2012/7c86333c886d2c3b7b002c3c3214f1d1 to your computer and use it in GitHub Desktop.
Save quxf2012/7c86333c886d2c3b7b002c3c3214f1d1 to your computer and use it in GitHub Desktop.
1. django admin export selected data to csv 2. django admin export data to csv without selected item;
"""
from django.contrib import admin
@admin.register(models.XXXX)
class XxxxxAdmin(ExportQueryBaseWithoutSelect, admin.ModelAdmin):
serializer_class = XxxSerializer #
...
"""
from django.contrib import admin
from django.contrib.admin import helpers
from django.http import HttpRequest, FileResponse
from django.utils.timezone import now
from rest_framework.serializers import ModelSerializer
from rest_framework_csv.renderers import CSVStreamingRenderer
class ExportQueryBase:
"""
export_to_csv
1. 导出选择的数据;
2. 不支持无选择对象导出
serializer_class
1. 需要在类中设置 serializer_class -> rest_framework.serializers
2. 如果没有设置, 使用rest_framework ModelSerializer 导出所有字段
from rest_framework.serializers import ModelSerializer
"""
_actions = ["export_to_csv"] # 允许在admin后台不选择 item的情况下继续;
serializer_class = None
@staticmethod
def auto_model_serializer(model):
class Serializer(ModelSerializer):
class Meta:
model = None
fields = '__all__'
Serializer.Meta.model = model
return Serializer
@staticmethod
@admin.action(description="Export Selected or All", permissions=('export_xxxx',))
def export_to_csv(model_admin: admin.ModelAdmin, request: HttpRequest, queryset):
model = model_admin.model
serializer_class = getattr(model_admin, 'serializer_class') or ExportQueryBase.auto_model_serializer(model)
c = serializer_class(queryset, many=True)
render_buffer = CSVStreamingRenderer().render(c.data, renderer_context={"bom": True, "encoding": "utf-8"})
response = FileResponse(render_buffer, content_type="text/csv; charset=utf-8")
response['Content-Disposition'] = f'attachment; filename="{model._meta.db_table}_{now().strftime("%Y-%m-%d_%H_%M_%S")}.csv"'
return response
def get_actions(self, request):
actions = super().get_actions(request)
if 'export_to_csv' not in actions:
actions['export_to_csv'] = (ExportQueryBase.export_to_csv, "export_to_csv", ExportQueryBase.export_to_csv.short_description)
return actions
class ExportQueryBaseWithoutSelect(ExportQueryBase):
"""
1. 导出当前查询条件的所有数据, 无需选择对象;
2. 导出选择的数据;
"""
def get_params_queryset(self, request):
# 根据当前的query_params 生成 queryset
return self.get_changelist_instance(request).get_queryset(request)
def changelist_view(self, request, extra_context=None):
selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) # 当前是否有选择对象
if not selected:
try:
action_index = int(request.POST.get("index", 0))
action = request.POST.getlist("action")[action_index]
if action in self._actions:
actions = self.get_actions(request)
# print(actions)
action_func = actions[action][0]
return action_func(self, request, self.get_params_queryset(request))
except IndexError as e:
pass
return super().changelist_view(request, extra_context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment