Django 3.2.1, Python 3.6, Postgres database
EDITED to take into account comments below, thanks!
I am writing a small Django app for storing product information. I coded the backend logic for uploading a local csv
file using a Custom Management Command
and am connecting this to the front end.
I am having trouble implementing the file upload -> having user upload products.csv
via a Form
submission to populate the database with file and display all products on one page.
I have stripped down my previous examples, as well as the suggested code below, to the simplest format to try to locate the problem.
Example of the csv
file:
name,sku,description
Brian James,skus-look-like-this,The products will have various descriptions. And multiple lines too.
models.py
class Product(models.Model):
name = models.CharField(max_length=500)
sku = models.CharField(max_length=500)
description = models.TextField(blank=False, null=False)
status = models.TextField(blank=False, null=False, default='inactive')
class Meta:
db_table = 'product'
Form for individual product
CRUD operations and for CSV file upload.
forms.py
class UploadForm(forms.Form):
csv_file = forms.FileField(required=False, widget=forms.FileInput(attrs={'class': 'form-control', 'placeholder':
'Upload "products.csv"', 'help_text': 'Choose a .csv file with products to enter'}))
/templates/upload.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="sent_file" />
<input type="submit" name="submit" value="Upload" />
</form>
views.py
# Function to upload the form, parse it, save to database
def create_upload(request):
if request.method == 'GET':
form = UploadForm()
return render(request, 'upload.html', {'form': form})
# If not GET method then proceed
form = UploadForm(request.POST, request.FILES)
print('FIRST FORM', form)
# Validate the form
if form.is_valid():
csv_file = form.cleaned_data['csv_file']
# Errors begin here ^, print(csv_file) = 'None'
form.save()
# Crashes here ^ with error: "AttributeError: 'UploadForm' object has no attribute 'save'
"
file_path = os.path.join(BASE_DIR, form.csv_file.url)
# printing `file_path` = `AttributeError: 'InMemoryUploadedFile' object has no attribute 'url'
`
# read the file contents and save the product details
with open(f'{file_path}, r') as products_csv:
products_file = csv.reader(products_csv)
next(products_file) # skip header row
for counter, line in enumerate(products_file):
name = line[0]
sku = line[1]
description = line[2]
p = Product()
p.name = name
p.sku = sku
p.description = description
p.status = random.choice(['active', 'inactive'])
p.save()
return redirect('/show_product')
Changing form.cleaned_data['csv_file']
to request.FILES['sent_file']
correctly prints the file name uploads.csv
but the url
is still inaccessible and still crashes on form.save()
. The only way I can print to terminal the contents of the uploaded file is by adding this:
csv_file = request.FILES['sent_file']
for i in csv_file:
print(i)
outputs:
b"'name','sku','description'\n"
b"'Zed','some-skus-more','descriptions. galore.'\n"
But the file still can't be uploaded and form.save()
can't be implemented.
I'm not sure how to continue debugging this. If anyone can point me in the right direction, would really appreciate it!