I have a django site that will take uploaded .xls files and merge them into one Workbook
I am having trouble merging the uploaded the Worksdheets. Here is a sample of my code:
import pyexcel
import openpyxl
from pyexcel.cookbook import merge_all_to_a_book
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
type_of_case = form.cleaned_data['Selection_type']
case = form.cleaned_data['Case']
new_name = type_of_case + '-' +case + '.xlsx'
file_names = []
objects=[]
for x in request.FILES.getlist('Files'):
filename = x.name
file_names.append(filename)
excel_ojects = x.read
objects.append(excel_ojects)
file_names.append(filename)
print (x.content_type)
merge_all_to_a_book(objects, outfilename=(new_name))
I've tried changing the merge_all_to_a_book to option (objects) and (file_names) but they both produce an error saying:
OSError: Unsupported file type
However when I print the content type I get:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Can anyone help me to merge these freaking spreadsheets?
Related
I am trying to access the csv file which i passed in my form and saved in media directory.
I am able to access the file if i manually enter the path(localhost://8000/media/1.csv)
but it throws an error saying "No such file or directory" when accessing from open function.
def home(request):
print("Rendering Home...")
if request.method == "POST":
uploaded_file = request.FILES['csvFile']
fs = FileSystemStorage()
name = fs.save(uploaded_file.name,uploaded_file)
url = fs.url(name)
csv_fp = open(f'{url}', 'r') //ERROR:"No such file or dir media/1.csv"
reader = csv.DictReader(csv_fp)
headers = [col for col in reader.fieldnames]
out = [row for row in reader]
return render(request, 'home.html', {'data' : out, 'headers' : headers})
return render(request,"home.html")
have you tried .path instead of .name
file = open(filename.path' 'rb').read()
The problem was the path being given to open function
csv_fp = default_storage.open(os.path.join(settings.MEDIA_ROOT, name), 'r')
simply did the trick :)
I trying to figure out a way to return multiple dataframes from a Django view as Zip HttpResponse(zip_file, content_type="application/x-zip-compressed")
I tried this:
import zipfile
import datetime
def makeZipfiles(df_list):
i = 0
with zipfile.ZipFile('some_zip.zip', 'w') as csv_zip:
for dfl in df_list:
csv_zip.writestr(f"file_{str(i)}.csv", dfl.to_csv(index=False))
i = i + 1
return csv_zip
and in the view, I have the following:
zip_file = makeZipfiles(df_list)
response = HttpResponse(zip_file, content_type="application/x-zip-compressed")
return response
but when I try to look at the zip file in the download folder, I get an error that the 'archive is either unknown format or damaged'. The exported file is 1KB size and when I open in notepad I see this content only
"<zipfile.ZipFile [closed]>"
Please advise if what I am trying to do is feasible and if so, please provide a sample code.
Thank you
I haven't tried this out myself yet, but it seems to fit your demand quite well.
https://georepublic.info/en/blog/2019/zip-files-in-django-admin-and-python/
The author describes in detail how to get .csv files from the different dataframes and zip them in the end to one file for download.
His final code was the following:
file_list = [
. . .,
UserInfoResource()
]
def getfiles():
fileSet = {}
date_now = dt.datetime.now().strftime('%Y%m%d%H%M')
for file in file_list:
dataset = file.export()
dataset = dataset.csv
name = file._meta.model.__name__ + date_now
fileSet[name] = dataset
return fileSet
def download_zip(request):
files = getfiles()
zip_filename = 'Survey_Data' + dt.datetime.now().strftime('%Y%m%d%H%M') + '.zip'
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
for k, file in files.items():
zip_file.writestr(k + '.csv', file)
zip_buffer.seek(0)
resp = HttpResponse(zip_buffer, content_type='application/zip')
resp['Content-Disposition'] = 'attachment; filename = %s' % zip_filename
return resp
I will update this answer if I manage to apply this on my own website.
(Let us know if you found a better answer in the meantime, thanks ;) )
I want to upload a file, what I am able to do with the code stated below, but I also need to save all the uploads in different folder with different names. If 2 users upload the same file from browser, then in the folder it should be saved with different name or Unique Identification number.
Following is my code:
views.py
from django.shortcuts import render
import openpyxl
def index(request):
if "GET" == request.method:
return render(request, 'myapp/index.html', {})
else:
excel_file = request.FILES["excel_file"]
# you may put validations here to check extension or file size
wb = openpyxl.load_workbook(excel_file)
# getting all sheets
sheets = wb.sheetnames
print(sheets)
# getting a particular sheet
worksheet = wb["Sheet1"]
print(worksheet)
# getting active sheet
active_sheet = wb.active
print(active_sheet)
# reading a cell
print(worksheet["A1"].value)
excel_data = list()
# iterating over the rows and
# getting value from each cell in row
for row in worksheet.iter_rows():
row_data = list()
for cell in row:
row_data.append(str(cell.value))
print(cell.value)
excel_data.append(row_data)
return render(request, 'myapp/index.html', {"excel_data":excel_data})
Give you a Django FileField way Implemention:
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
suffix = filename[filename.rindex(".")+1:]
return 'upfiles/{0}/{1}.{2}'.format(instance.user.username, get_randomfilename(),suffix)
class Picture(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
file = models.ImageField(upload_to=user_directory_path)
date_added = models.DateTimeField(auto_now_add=True)
#parser_classes((MultiPartParser,))
#permission_classes((IsAuthenticated, ))
def upload_picture(request):
'''
:input :{"file":f}
:return:{"id":pictureId}
'''
if "file" in request.FILES:
f = request.FILES["file"]
picture = Picture()
picture.user= request.user
picture.file = f
picture.save()
return Response(data={"id":picture.id})
else:
return Response({},status=status.HTTP_400_BAD_REQUEST)
I need user to upload an excel file via the form provided and i need to process that uploaded excel file to save the data in my model.
models.py
class Patient_Record(models.Model):
Patient_id=models.IntegerField(unique=True)
Patient_sex=models.CharField(max_length=1,choices=Gender)
Patient_name=models.CharField(max_length=20)
Patient_sugar=models.DecimalField(decimal_places=3,max_digits=6)
Patient_chlorestrol=models.DecimalField(decimal_places=3,max_digits=6)
Patient_iron=models.DecimalField(decimal_places=3,max_digits=6)
Patient_haemoglobin=models.DecimalField(decimal_places=3,max_digits=6)
def __str__(self):
return self.pat_name
I have simple form to upload the file.
<form method="POST" class="post-form" action="../Uploaded_file" enctype="multipart/form-data" name="myfile">{% csrf_token %}
{{ upload_form.as_p }}
<input type="submit" value="Upload" name="Upload" class="btn btn-primary">
</form>
Can someone help me with the code to parse a excel file using POST to this model.
I tried using many different methods but couldn't succeed in it.
You require xlrd library to extract the data from excel sheet.
Check out following link https://pypi.python.org/pypi/xlrd
This is the example snippet. You may modify it according to your code.
In Forms.py create a model form with following field.
class UpdateDetailsForm(forms.Form):
excel_file = forms.FileField(label='Excel File',required=False,validators=[validate_file_extension])
Then in corresponding views.py
def update_details(request):
message=''
if request.method == 'POST':
form = UpdateDetailsForm(request.POST,request.FILES)
if form.is_valid():
#import your django model here like from django.appname.models import model_name
excel_file = request.FILES['excel_file']
i=0
try:
import os
import tempfile
import xlrd
fd, tmp = tempfile.mkstemp()
with os.fdopen(fd, 'w') as out:
out.write(excel_file.read())
book=xlrd.open_workbook(fd)
sh = book.sheet_by_index(0)
for rx in range(1,sh.nrows):
obj=Patient_Record(Patient_id=str(sh.row(rx)[0].value),Patient_sex=str(sh.row(rx)[1].value)) # similiary populate according to your model
obj.save()
i=i+1;
finally:
os.unlink(tmp)
else:
message='Invalid Entries'
else:
form = UpdateDetailsForm()
return render_to_response('admin/import_data.html', {'form':form,'message':message},context_instance=RequestContext(request))
In Python 3.6 and Django 2.0 the following rises the error
Exception Type: PermissionError
Exception Value:[WinError 32]
def upload_file(request):
message=''
if request.method == 'POST':
form = FormUploadFileData(request.POST, request.FILES)
if form.is_valid():
from projects.models import Project
excel_file = request.FILES['excel_file']
try:
import os
import tempfile
import xlrd
fd, tmp = tempfile.mkstemp() # create two temporary file
with os.open(fd, 'wb') as out: # create new file objects
out.write(excel_file.read())
book = xlrd.open_workbook(fd)
sheet = book.sheet_by_index(0)
obj=Project(
project_title = sheet.cell_value(rowx=1, colx=1),
project_sector = sheet.cell_value(rowx=2, colx=1),
project_location = sheet.cell_value(rowx=3, colx=1),
project_tot_cost = sheet.cell_value(rowx=4, colx=1),
project_descr = sheet.cell_value(rowx=5, colx=1),
project_fund = sheet.cell_value(rowx=6, colx=1),
project_cofin = sheet.cell_value(rowx=7, colx=1),
project_applicant = sheet.cell_value(rowx=8, colx=1)
)
obj.save()
finally:
os.unlink(tmp)
else:
message='Invalid Entries'
else:
form = FormUploadFileData()
return render(request,'upload.html', {'form':form,'message':message})
There is an issue in the solution proposed:
book=xlrd.open_workbook(fd) should be book=xlrd.open_workbook(tmp) as open_workhook search for a file path
[Worked in Python 3.6, Django 2.0]
excel_file = request.FILES['excel_file']
import os
import tempfile
import xlrd
fd, path = tempfile.mkstemp() # mkstemp returns a tuple: an integer (index) called file descriptor used by OS to refer to a file and its path
try:
with os.fdopen(fd, 'wb') as tmp:
tmp.write(excel_file.read())
book = xlrd.open_workbook(path)
sheet = book.sheet_by_index(0)
obj=Project(
project_title = sheet.cell_value(rowx=1, colx=1),
project_sector = sheet.cell_value(rowx=2, colx=1),
project_location = sheet.cell_value(rowx=3, colx=1),
project_tot_cost = sheet.cell_value(rowx=4, colx=1),
project_descr = sheet.cell_value(rowx=5, colx=1),
project_fund = sheet.cell_value(rowx=6, colx=1),
project_cofin = sheet.cell_value(rowx=7, colx=1),
project_applicant = sheet.cell_value(rowx=8, colx=1)
)
obj.save()
finally:
os.remove(path)
I'm building a web app in Django.
I have a form that sends a file to views.py.
Views:
#login_required(login_url=login_url)
def addCancion(request):
if request.method == 'POST':
form2 = UploadSong(request.POST, request.FILES)
if form2.is_valid():
if(handle_uploaded_song(request.FILES['file'])):
path = '%s' % (request.FILES['file'])
ruta = "http://domain.com/static/canciones/%s" % path
usuario = Usuario.objects.get(pk=request.session['persona'])
song = Cancion(autor=usuario, cancion=ruta)
song.save()
return HttpResponse(ruta)
else:
return HttpResponse("-3")
else:
return HttpResponse("-2")
else:
return HttpResponse("-1")
I'm trying to upload only the MP3 files, but I don't know how to make this filter.
I tried a class named "ContentTypeRestrictedFileField(FileField):" and doesn't work.
How can I get the file type in views.py?
Thanks!
You could also use the clean() method from the form, which is used to validate it. Thus, you can reject files that are not mp3. Something like this:
class UploadSong(forms.Form):
[...]
def clean(self):
cleaned_data = super(UploadSong, self).clean()
file = cleaned_data.get('file')
if file:
filename = file.name
print filename
if filename.endswith('.mp3'):
print 'File is a mp3'
else:
print 'File is NOT a mp3'
raise forms.ValidationError("File is not a mp3. Please upload only mp3 files")
return file
with import mimetypes, magic:
mimetypes.MimeTypes().types_map_inv[1][
magic.from_buffer(form.cleaned_data['file'].read(), mime=True)
][0]
gives you the extension as '.pdf' for example
https://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form
http://docs.python.org/2/library/mimetypes.html#mimetypes.MimeTypes.types_map_inv
https://github.com/ahupp/python-magic#usage
for get direct of request:
import os
extesion = os.path.splitext(str(request.FILES['file_field']))[1]
or get extesion in db - model.
import os
file = FileModel.objects.get(pk=1) # select your object
file_path = file.db_column.path # db_column how you save name of file.
extension = os.path.splitext(file_path)[1]
You mean this:
u_file = request.FILES['file']
extension = u_file.split(".")[1].lower()
if(handle_uploaded_song(file)):
path = '%s' % u_file
ruta = "http://example.com/static/canciones/%s" % path
usuario = Usuario.objects.get(pk=request.session['persona'])
song = Cancion(autor=usuario, cancion=ruta)
song.save()
return HttpResponse(content_type)
You can use request.FILES["file_field_name"].content_type
my_file = request.FILES["file_field_name"]
if my_file.content_type != 'text/csv':
print("Your file must be a CSV type")
Using FileType.py library.
Example:
kind = filetype.guess('tests/fixtures/sample.jpg')
if kind is None:
print('Cannot guess file type!')
return
print('File extension: %s' % kind.extension)
print('File MIME type: %s' % kind.mime)
Using MimeTypes().guess_extension() method. Check snippet below.
# guess the file extension
file_obj.seek(0)
mime = magic.from_buffer(file_obj.read(), mime=True)
extension = mimetypes.MimeTypes().guess_extension(mime)
>>> print extension
.jpeg