Data is very much important. Specially, when you are working on a project which is already in production you must take care of your existing data. If data is lost somehow your client gonna kill you. So, we save the data externally in different format like json or csv. In the first place, we will see how to export data of a table in .csv (Comma Separated Value) format from django’s default admin site and then we will work on restoring that data into table row/model instance.

Export CSV files from Django Admin.

In our admin site we will create a ModelMixin. Let’s name it ‘ExportCsvMixin’. The ‘export_as_csv’ function of the mixin will convert the model instances into CSVs.

# EXPORT AS CSV
class ExportCsvMixin:
    def export_as_csv(self, request, queryset):
        meta = self.model._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 queryset:
            row = writer.writerow([getattr(obj, field) for field in field_names])
        return response
    
    export_as_csv.short_description = "Export Selected"

“field_names” is the list of names of column names. The csv.writer() function is used to create a writer object. The writer.writerow() function is then used to write single rows to the CSV file.

Now, let’s add the “export_as_csv” function of that mixin in the ‘actions’ list of ‘PersonAdmin’ which will display in the ‘Action’ dropdown in the admin panel.

class PersonAdmin(admin.ModelAdmin, ExportCsvMixin):
    actions = ["export_as_csv"]

Output:

After selecting ‘Export Selected’ we will click the ‘Go’ button this will actually call the ‘export_as_csv’ function and the function will start converting the queryset objects into csv files and the filename will be in this format “app_name.model_name.csv” i.e. first_app.person.csv.

first_app.person.csv file.

Import CSV file in Django Admin

We have already seen how to export data as csv. Now it’s turn to put the data back into database table. That means to convert the csv file rows into objects. For that we need to create a ‘form’ in the first place to upload the csv file.

forms.py

# A form to upload files
class CsvImportForm(forms.Form):
    csv_file = forms.FileField()

change_list.html

{% extends 'admin/change_list.html' %}

{% block object-tools %}
<a href="import-csv/">IMPORT CSV</a>
<br />
{{ block.super }}

{% endblock %}

We wll see an ‘IMPORT CSV’ link in the top of the table. We will redirect this into ‘csv_form.html’

Now we will write a function named ‘import_csv’. We will need to import the ‘csv’ moule of python first. I would suggest you to read the comments written inside the import_csv() function.

import csv

 
class PersonAdmin(admin.ModelAdmin, ExportCsvMixin):
    list_display = ['id','full_name','gender','email',]
    actions = ["export_as_csv"]

    change_list_template = "admin/change_list.html"

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
    
            path('import-csv/', self.import_csv),
        ]
        return my_urls + urls
        
    def import_csv(self, request):
        if request.method == "POST":
            csv_file = request.FILES["csv_file"]

            # Create Hero objects from passed in data
            file_data = csv_file.read().decode("utf-8")          
            lines = file_data.split("\n")
  
            #loop over the lines and save them in db. If error shows up , store as string and then display
            for line in lines:                                        
                fields = line.split(",")
                if len(fields) >= 5:
                    # Skip the list of column names i.e 'id', 'first_name' etc
                    if fields[0] != 'id':
                        # remove starting and trailing spaces from gender.
                        gender = fields[4].strip()
                        # create person object from the csv rows.
                        Person.objects.create(
                                    id = fields[0], 
                                    first_name = fields[1], 
                                    last_name = fields[2], 
                                    email = fields[3], 
                                    gender = gender,
                                              )
      
            self.message_user(request, "Your csv file has been imported")

            return redirect("..")

        form = CsvImportForm()
        payload = {"form": form}
        
        return render(request, "admin/csv_form.html", payload)

Now to show the upload form to the user we will use a template. The template will look like that:

csv_form.html

{% extends 'admin/base.html' %}
{% block content %}
<div>
    <form action="." method="POST" enctype="multipart/form-data">
    {{ form.as_p }}
    {% csrf_token %}
    <button type="submit">Upload CSV</button>
    </form>
</div>
<br />
{% endblock %}

Output:

After importing the file…

There are a lots of way to do it like using Pandas library or django-csvimport but here we have seen an easy one. To read more tutorials on django and django rest framework here.

+ posts

Author | Python-Django Developer

+ posts

Full-stack Developer (Python | Django | React | React-Native | Angular | Vue)