Makina Blog

Le blog Makina-corpus

Comment facilement exporter en CSV depuis l'admin Django


La possibilité d'exporter en CSV est une demande fréquente. Grâce à l'admin Django, nous pouvons mettre cela en place très facilement, comme nous allons le voir dans cet article.

Nous utiliserons deux choses pour arriver à notre fin. Tout d'abord, la bibliothèque csv standard, qui nous offre la possibilité de facilement créer un CSV :

import csv


writer = csv.writer(csvfile)
writer.writerow(['une colonne', 'une seconde colonne'])

Django permet de créer une réponse HTTP utilisant ceci très facilement, tout est expliqué en détail dans la documentation officielle :

import csv
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(
        content_type='text/csv',
        headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
    )

    writer = csv.writer(response)
    writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
    writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])

    return response

Puis pour l'intégrer dans l'admin, nous implémenterons une action :

from django.contrib import admin
from django.utils.translation import gettext_lazy as _


class UserAdmin(admin.ModelAdmin):
    actions = ['export_csv']

    @admin.action(description=_('Exporter en CSV'))
    def export_csv(self, request, queryset):
        [...]

Les actions permettent de travailler sur les objets sélectionnés dans la liste. Si une action retourne une réponse HTTP, alors c'est cette réponse qui sera renvoyée au navigateur ! En utilisant ce que nous savons désormais, et en combinant tout ça, nous avons déjà notre solution :

import csv

from django.contrib import admin
from django.http import HttpResponse
from django.utils.translation import gettext_lazy as _


class UserAdmin(admin.ModelAdmin):
    actions = ['export_csv']

    @admin.action(description=_('Exporter en CSV'))
    def export_csv(self, request, queryset):
        response = HttpResponse(
            content_type='text/csv',
            headers={'Content-Disposition': 'attachment; filename="utilisateurs.csv"'},
        )

        writer = csv.writer(response)
        for user in queryset:
            writer.writerow([
                user.id,
                user.username,
                user.email,
                user.first_name,
                user.last_name,
            ])
        return response

Il suffit ensuite de sélectionner les éléments que nous voulons exporter, de choisir l'action d'export, puis de cliquer sur le bouton. Pour tout exporter, nous pouvons cliquer sur la case en haut à gauche, puis cliquer sur "Sélectionner tous les X éléments" si nous avons plusieurs pages :

Exporter depuis l'admin en CSV

Et voila, à nous les CSV sans effort, merci Django 😊 !

Edit: Merci à Jean-Philippe Vincent de nous avoir fait part de sa méthode, pratique si l'on veut exporter tous les champs sans se prendre la tête :

writer.writerow([key for key, value in queryset.values()[0].items()])
writer.writerows(queryset.values_list())

Ou, préférence de ma part pour garder la main sur les données exportées :

writer.writerow(['id', 'username', 'email'])
writer.writerows(queryset.values_list(['id', 'username', 'email']))

Cette méthode a en plus l'avantage de limiter la requête SQL et ne pas instancier les objets, ce qui n'est pas négligeable en terme de performance.

Formations associées

Django

Django initiation

Nantes Du 13 au 15 septembre 2022

Voir la formation

Django

Django avancé

A distance (foad) Du 7 au 9 novembre 2022

Voir la formation

Python

Python

Toulouse Du 20 au 22 septembre 2022

Voir la formation

Actualités en lien

Image
Django logo
08/07/2020 - 13:25

Présentation de django-tracking-fields

Suivi de modification d'objets Django

Voir l'article
Image
Django logo
28/08/2018 - 13:32

Internationalisation avec Django

En tant que développeurs nous sommes parfois confronté à la problématique de l'accessibilité des utilisateurs parlant différentes langues. Cet article est à destination des développeurs Django souhaitant découvrir l'internationalisation (i18n) et propose un parcours pas à pas dans cet exercice.

Voir l'article
Image
Django logo
09/07/2013 - 15:50

Présentation de Django-Safedelete

Masquage d'objets en base de données une alternative à la suppression définitive.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus