Tony Carter
Tony Carter

Reputation: 43

Django - UnboundLocalError

I have a function in a view that I am using to upload CSV data and write to a DB. That part is working. However, when I try to check if there was data updated or created, I am getting an error which reads:

"local variable 'created' referenced before assignment".

The function in the view is as follows

def bookings_upload(request):

    prompt = {
        'order': "Please import a valid CSV file"
    }
    if request.method == "GET":
        return render(request, 'booking_app/importBookings.html', prompt)

    csv_file = request.FILES['bookings']

    if not csv_file.name.endswith('.csv'):
        messages.error(request, "This file is not a .csv file.")
        return redirect('/booking_app/bookings_upload/') 

    data_set = csv_file.read().decode('utf-8')
    io_string = io.StringIO(data_set)
    next(io_string)

    for column in csv.reader(io_string, delimiter=',', quotechar="|"):
        _, created = Bookings.objects.update_or_create(
            book_date=column[0],
            grower_number=column[1],
            bales_booked=column[3],
            sale_date=column[6],
            book_id=column[11],
            reoffer=column[12]
        )
    ) 

    if created:
        messages.success(request, "Bookings have been imported successfully")
    else:
        messages.warning(request, "No new bookings were imported. Please check/verify your csv file")   

    context = {}
    return render(request, 'booking_app/importBookings.html', context)

What am I missing? Any assistance will be greatly appreciated.

Upvotes: 2

Views: 77

Answers (2)

lmiguelvargasf
lmiguelvargasf

Reputation: 69735

The problem is that if you read nothing from the csv file you will not define created. Try adding the following before you start the loop:

created = None

However, as BearBrown has suggested, this will solve your error, but you will still have a logic error. In order to fix both use the following code. This will show a message for each row:

for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    _, created = Bookings.objects.update_or_create(
        book_date=column[0],
        grower_number=column[1],
        bales_booked=column[3],
        sale_date=column[6],
        book_id=column[11],
        reoffer=column[12]
    ) 

    if created:
        messages.success(request, "Bookings have been imported successfully")
    else:
        messages.warning(request, "No new bookings were imported. Please check/verify your csv file")

If you want to show just one general message:

created = None
created_records = 0

for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    _, created = Bookings.objects.update_or_create(
        book_date=column[0],
        grower_number=column[1],
        bales_booked=column[3],
        sale_date=column[6],
        book_id=column[11],
        reoffer=column[12]
    )

    if created:
        created_records += 1



if created is None:
    messages.success(request, "No records were read from file.")
elif created_records > 0:
    messages.success(request, f"{created_records} bookings have been imported successfully")
else:
    messages.warning(request, "No new bookings were imported. Please check/verify your csv file")

The previous code assumes you use Python 3.6+, if using a previous version, change this line:

messages.success(request, f"{created_records} bookings have been imported 

to:

messages.success(request, "{created_records} bookings have been imported successfully".format(created_records=created_records))

Upvotes: 1

AKX
AKX

Reputation: 168903

@lmiguelvargasf's answer explains what's happening, but I'd reckon a better refactoring, that also adds more information, would be:

n_created = 0
for column in csv.reader(io_string, delimiter=",", quotechar="|"):
    _, created = Bookings.objects.update_or_create(
        book_date=column[0],
        grower_number=column[1],
        bales_booked=column[3],
        sale_date=column[6],
        book_id=column[11],
        reoffer=column[12],
    )
    if created:
        n_created += 1

if n_created:
    messages.success(request, "%d bookings have been imported successfully" % n_created)
else:
    messages.warning(request, "No new bookings were imported. Please check/verify your csv file")

Upvotes: 1

Related Questions