Export Django Model Class to .csv file

 

 Hello,

Django offers a great out-of-the-box Administration Interface to help you interact with all your database data but sometimes you need a backup of your data in case you had to drop the database and recreate it for different reasons:

  • Changing the database structure
  • Project deployment

this is where this blog post will save you a lot of time by teaching you setp-by-step, how to create a Django View to Export a Model (or many Models) to a .csv file, let's get started!

  • Create a new Django project (in my case i'm using version 2.2 you can use any version you want)
  • Create a new App call it whatever you want
  • Navigate to /new_app/models.py file and create a Django class, to keep this tutorial simple we will create a Brand class with two fields (name, slug)

Note: the id field is created automatically by Django ORM 

Or you can copy/past this into your models.py:

 class Brand(models.Model):
    name = models.CharField(max_length=200,db_index=True)
    slug = models.SlugField(max_length=200,unique=True)
In the same App create a new file for your forms call it forms.py:

Copy/past this into it:

OBJECTS_CHOICES = [
('Brand', 'Brand',),
('ParentCategory', 'ParentCategory',),
('Category', 'Category',),
('Store', 'Store',),
('Product', 'Product',),
('Order', 'Order',),
('OrderItem', 'OrderItem',),
]
class ExportDataForm(forms.Form):
    class_to_export = forms.ChoiceField(label='Ready to Export',choices=OBJECTS_CHOICES,required=True)
So, what you need to focus on here is the OBJECTS_CHOICES field that will be visible to the user from the template (we will create it later) and to explain it quickly:

    You got OBJECTS_CHOICES=[(x1,y1),(x2,y2),]

the x must be indentical to the Django Model Name that you want to Export to a .csv File, the y can be whatever you want(what the user will see and interact with).

Now create an HTML file called whateveryoulike.html under the Templates folder(create one at the root level of your project if you don't have it).

It's just a simple HTML file that will send us a FORM(POST):
In my Case:

{% extends "main.html" %}
{%block content%}
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div class="container">


<form class="" action="" method="POST">
{% csrf_token %}
{{form|crispy}}
<input type="submit" name="" value="Export CSV" class="btn btn-success">
</form>
    </div>
  </body>
</html>
{%endblock%}
Note: I have a main.html file and i have used crispy_forms, you should know what both means, if not, remove the extends line, the block content line, the load crispy_forms_tags line and the filter on the form {{form|crispy}} so it becomes just {{form}}.

Now let's move to our views.py file, here we will have all the logic of exporting the data to a .csv file, copy/past this into your file:

def export_to_csv(request):
    form=ExportDataForm()
    if request.method == 'POST':
        form=ExportDataForm(request.POST)
        models = {
            model.__name__: model for model in apps.get_models()
        }
        if form.is_valid():
            model_name=form.cleaned_data['class_to_export']
        model_class = models[model_name]
        meta = model_class._meta
        field_names = [field.name for field in meta.fields]

        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
        writer = csv.writer(response)

        writer.writerow(field_names)
        for obj in model_class.objects.all():
            row = writer.writerow([getattr(obj, field) for field in field_names])

        return response
    if request.method == 'GET':
        context={'form':form}
        return render(request, 'shopApp/data_export.html', context)

Let's talk about the logic in this view real quick, if the request is GET, we will just return the form to the template in my case "shopApp/data_export.html", but if the request is POST we will first create an instance from our ExportDataForm and save it into a variable called form, then we will get all the models names using apps.get_models() method,
Note: to use the
apps.get_models() you must first from django.apps import apps.

Now all we need to do is to link our view to a path and we do that using the urls.py file by adding a path method to the urlpatterns list:

path('data_export/',views.export_to_csv,name='data_export'),

Now i may have forgot to tell you to import some packages to the views.py file:

import csv, io
from django.contrib import messages
from django.apps import apps 

from django.shortcuts import render, get_object_or_404, redirect
from .models import *

Now we are ready to go, lets run our project using the command:

py manage.py runserver

and the result should be something similar to this (after some bootstrap magic):

 


After you select the model that you want to export, and click on Export CSV button you should get a file with name as app_name.model_name.csv.

The out put of the file should be similar to this:

 

 I hope the tutorial was simple, I will soon publish a fullstack Django (E-commerce Platform) if you're interested follow me on github:

github.com/ahmedsmaali5

I would like to thank some people that helped me like Myzel394 for his answer on this stackoverflow question:
https://stackoverflow.com/questions/1125107/django-how-can-i-find-a-list-of-models-that-the-orm-knows

Have a nice day! and don't forget to checkout other posts on Developers Toolkit.

Comments