У меня есть форма для пользователей для загрузки файла CSV.
Если пользователь не выбирает файл из P C и нажимает кнопку Отправить, шаблон должен отображаться с ошибками, но вместо этого он возвращает:
MultiValueDictKeyError at /productos/productos-csv/
'file'
Я понимаю, что это потому, что я не могу найти:
elif request.method == "POST":
csv_file = request.FILES['file']
Но как я могу сказать Django просто отрисовать шаблон и показать сообщение об ошибке «Пожалуйста, загрузите файл».
HTML:
{% if form.errors %}
<h1>Errors</h1>
{% endif %}
{% if messages %}
{% for message in messages %}
<div>
<!-- | means OR operator-->
<strong>{{message|safe}}</strong>
</div>
{% endfor %}
{% else %}
<h1>Creación de productos</h1>
<p>{{orden}}</p>
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label for="file1">Subir archivo</label>
<input type="file" id="file1" name="file"><br>
<small>Solo se aceptan CSV files</small>
<button type="submit">Crear productos</button>
</form>
{% endif %}
На мой взгляд, я добавляю сообщение об ошибке, чтобы сообщить пользователю о загрузке файл:
if not csv_file:
messages.error(request, 'Por favor, seleccione un archivo CSV')
views.py:
def products_upload(request):
# declaring template
template = "scolarte/productos/subir-productos.html"
data = Product.objects.all()
# prompt is a context variable that can have different values depending on their context
prompt = {
'orden': 'El orden de las columnas del archivo CSV debe ser: producto, direccion, referencia, provincia, cantón, parroquia',
'productos': data
}
# GET request returns the value of the data with the specified key.
if request.method == "GET":
return render(request, template, prompt)
elif request.method == "POST":
csv_file = request.FILES['file']
if not csv_file:
messages.error(request, 'Por favor, seleccione un archivo CSV')
# let's check if it is a csv file
# if not csv_file.name.endswith('.csv'):
# messages.error(request, 'El archivo no es un archivo CSV')
data_set = csv_file.read().decode('iso-8859-1')
# setup a stream which is when we loop through each line we are able to handle a data in a stream
io_string = io.StringIO(data_set)
next(io_string)
for column in csv.reader(io_string, delimiter=',', quotechar="|"):
try:
_, created = Product.objects.update_or_create(
category=Category.objects.get(name=column[0]),
subcategory=SubCategory.objects.get(system_id=column[1]),
brand=Brand.objects.get(name=column[2]),
system_id=column[3],
large_name=column[4],
short_name=column[5],
slug=column[6],
sku=column[7],
description=column[8],
price=column[9],
stock=column[10],
image=column[11],
available=column[12]
)
except IntegrityError as e:
if 'unique constraint' in e.args:
continue
context = {}
return redirect('products:products_upload')