Home > Net >  Django csv upload to db works but throws error
Django csv upload to db works but throws error

Time:07-08

I have created an app named customer within a project named Website using django. I have created a csv upload in the admin area which is connected to the Postgres db.

An error occurs when I upload the CSV returning:
Exception Type:     IndexError
Exception Value:    list index out of range

However the CSV file is still added to the db but the error screen is displayed. Even more strangely if I a notepad doc as csv containing the data and upload that I get no error until I try to upload a second data set. If I save an excel doc as csv I get the error. Where am I going wrong ?

 Models.py
    class customer(models.Model):
        name = models.CharField(max_length=50, blank=True)
        balance = models.CharField(max_length=120, blank=True)    
    
        def __str__(self):
            return self.name

Admin.py
from django.contrib import admin
from django.urls import path
from django.shortcuts import render, redirect
from .models import customer
from django import forms
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse
from import_export import resources


class data(resources.ModelResource):

    class Meta:
        model = customer


class CsvImportForm(forms.Form):
    csv_upload = forms.FileField()


class CustomerAdmin(admin.ModelAdmin):
    list_display = ('name', 'balance',)

    def get_urls(self):
        urls = super().get_urls()
        new_urls = [path('upload-csv/', self.upload_csv), ]
        return new_urls   urls



   
   
    def upload_csv(self, request):       

        if request.method == "POST":
            print("action is POST")
            csv_file = request.FILES["csv_upload"]

            if not csv_file.name.endswith('.csv'):
                messages.warning(request, 'The wrong file type was uploaded')
                return HttpResponseRedirect(request.path_info)

            file_data = csv_file.read().decode("utf-8")
            csv_data = file_data.split("\n")

            for x in csv_data:
                fields = x.split(",")
                created = customer.objects.update_or_create(
                    name=fields[0],
                    balance=fields[1],
                )
        
        

        form = CsvImportForm()
        data = {"form": form}
        return render(request, "admin/search/csv_upload.html", data)
         

        

admin.site.register(customer, CustomerAdmin)



csv_upload.html
{% extends 'admin/index.html' %}

{% block content %}
    <div>
        <form action ="." method="POST" enctype="multipart/form-data">
            {{ form.as_p }}
            {% csrf_token %}
            <h1>Hello World upload files here to db</h1>
            <button type="submit">Upload file</button>
        </form>
    </div>
{% endblock %}


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

{% load static %}

{% block content %}

    <br><br>
    <a href="upload-csv/">Upload a csv file</a>
    <br><br><br>

    <!-- Gives us all the other elements ont he page we want to access. -->
    {{ block.super }}

{% endblock %}


Traceback error:
Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/admin/search/customer/upload-csv/

Django Version: 4.0.5
Python Version: 3.9.2
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'search',
 'django.contrib.postgres',
 'import_export']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\acart\Desktop\New folder\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\acart\Desktop\New folder\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\acart\Desktop\New folder\website\search\admin.py", line 51, in upload_csv
    balance=fields[1],

Exception Type: IndexError at /admin/search/customer/upload-csv/
Exception Value: list index out of range

CodePudding user response:

Due to the nature of csv, you need to check if the length of your field item is 2.

i.e.

            for x in csv_data:
                fields = x.split(",")
                if len(fields) == 2:
                    created = customer.objects.update_or_create(
                        name=fields[0],
                        balance=fields[1],
                    )

This way, you skip processing lines which are empty. Note that I'm assuming your expected field lengths is 2.

  • Related