Reputation: 43
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
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
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