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 :)
Related
I have an uploadform and I want to test it. But there is a problem.
def test_if_can_upload_file(self):
with open('app_blog/tests/test.txt') as file:
self.client.post(reverse('csv_blog'), {'attachment': file})
test_file = file.read()
self.assertEqual(test_file, 'test file')
When I test it, there is an error:
self.assertEqual(test_file, 'test file')
AssertionError: '' != 'test file'
+ test file
Why is my file shown like it is empty? Actually it is not empty.Or maybe I test my form in a wrong way?
form
class UploadBlogForm(forms.ModelForm):
file = forms.FileField()
class Meta:
model = Blog
fields = 'file',
view
def upload_blog(request):
if request.method == "POST":
upload_file_form = UploadBlogForm(request.POST, request.FILES)
if upload_file_form.is_valid():
blog_file = upload_file_form.cleaned_data['file'].read()
blog_str = blog_file.decode('utf-8').split('\n')
csv_reader = reader(blog_str, delimiter=":::", quotechar='"')
Your self.client.post(…) will already exhaust the file handler and read the entire content of the file, this thus means that when you call file.read(), the cursor already moved to the end of the file, and thus returns an empty string.
You should reopen the file and read the file from the beginning, so:
def test_if_can_upload_file(self):
with open('app_blog/tests/test.txt') as file:
self.client.post(reverse('csv_blog'), {'attachment': file})
with open('app_blog/tests/test.txt') as file:
test_file = file.read()
self.assertEqual(test_file, 'test file')
I want save document when uploaded and run pandas script and save that script but also to forward to user do download it. How to do it simple way?
This is how I tried to do it, upload and save upload works, but pandas script is not working.
def my_view(request):
message = 'Upload as many files as you want!'
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
#This part is doing calculations for uploaded file
dfs = pd.read_excel(newdoc, sheet_name=None)
with pd.ExcelWriter('output_' + newdoc + 'xlsx') as writer:
for name, df in dfs.items():
print(name)
data = df.eval('d = column1 / column2')
ooutput = data.eval('e = column1 / d')
ooutput.to_excel(writer, sheet_name=name)
output = io.BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
newdoc.to_excel(writer, index=False)
writer.save()
output.seek(0)
response = HttpResponse(output,
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=%s.xlsx' % 'Download'
return response
return redirect('results')
else:
message = 'The form is not valid. Fix the following error:'
else:
form = DocumentForm()
documents = Document.objects.all()
context = {'documents': documents, 'form': form, 'message': message}
return render(request, 'list.html', context)
def results(request):
documents = Document.objects.all()
context = {'documents': documents}
return render(request, 'results.html', context)
dfs = pd.read_excel(newdoc, sheet_name=None)
You are passing newdoc here, which is your model, not a IO object.
Try
dfs = pd.read_excel(newdoc.docfile, sheet_name=None)
or
dfs = pd.read_excel(newdoc.docfile.file, sheet_name=None)
This is the not answer but my suggestion, you are following the wrong way of implementation.
You can set background process in Celery
After the job is done in Celery you can mail/notify the User with download URL.
The above given solution will be long but scalable and performance-oriented as well.
I would like to add/write information to text files (on the disk) using flask (with just python the program works but when I implement it with the rest nothing happens).
view.py :
#app.route('/add', methods=['GET','POST'])
def add_entry():
if request.method == 'POST':
filename = request.form['file_name']
read_file(filename) #returns a dictionnary list
write_file(filename)
return redirect(url_for('index'))
else :
return render_template("file_add.html",title='Add a file', items=items)
and function.py:
def write_file(filename):
with open("app/static/DATA/{}".format(filename), "w") as f:
global items
items2 = [{ 'fixed_address': request.form['mac_address'],
'hardware': request.form['ip_address'],
'host': request.form['host_name'],
'comment': request.form['comment']}]
items.append(items2)
f.write(items)
Nothing happens when I submit, the file stays the same. What am I doing wrong?
I saw that f.write() might not work with other stuff beside strings but even the other solutions don't work and f.write('random_string') does nothing as well.
1) Pass request obj to your function to use it in it's body to retrieve POST params. In your code (when you do not pass request obj to your write function) you cannot get desired params because request is not a flask request object in write func body, just an undefined var. To use flask request obj in your function body - you need to pass it as a second argument:
view.py:
#app.route('/add', methods=['GET','POST'])
def add_entry():
if request.method == 'POST':
filename = request.form['file_name']
read_file(filename) #returns a dictionnary list
write_file(filename, request)
return redirect(url_for('index'))
else :
return render_template("file_add.html",title='Add a file', items=items)
function.py:
def write_file(filename, request):
with open("app/static/DATA/{}".format(filename), "w") as f:
global items
items2 = [{ 'fixed_address': request.form['mac_address'],
'hardware': request.form['ip_address'],
'host': request.form['host_name'],
'comment': request.form['comment']}]
items.append(items2)
f.write(items)
2) Always use full path here with open("app/static/DATA/{}".format(filename), "w") as f:
3) Use json.dump() to write your data to a file:
import json
obj = [{"123": "123"}]
with open("<full_path>", "w") as f:
json.dump(obj, f, indent=4)
4) Do not use filename = request.form['file_name'] - use filename = request.form.get('file_name') instead.
I am trying to write the content in CSV file and Here I need to download that file and save that same file into upload folder. My code is below.
if request.method == 'POST':
param = request.POST.get('param')
report = Reactor.objects.all()
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename='+uuid.uuid4()+'.csv'
writer = csv.writer(response)
writer.writerow(['Name', 'Status', 'Date'])
for rec in report:
if rec.status == 1:
status = 'Start'
if rec.status == 0:
status = 'Stop'
if rec.status == 2:
status = 'Suspend'
writer.writerow([rec.rname, status, rec.date])
#return response
u = urllib.URLopener()
f = u.open(param)
open("down.txt","w").write(f.read())
pers = User.objects.get(pk=request.session['id'])
root = []
user_name = pers.uname
count = 1
root.append(
{'username': user_name,
'count': count
})
return render(request, 'plant/home.html',
{'user': root, 'count': 1})
Here I am setting the database values inside one CSV file and that file is named as unique id. Here I need to save that file inside Upload folder and that folder path will set inside settings.py file and also same file will be downloaded as well.
You should try to generate your CSV into a buffer an then use it to save it to the file system and use it again to return the CSV as the respone. Something like this
import csv
import os
import shutil
from io import StringIO
from django.http import HttpResponse
from django.conf import settings
def my_view(request):
csvbuffer = StringIO
writer = csv.writer(csvbuffer)
# Write data from the DB here into the CSV buffer
# Write the file to the file system
path = os.path.join(settings.FILE_PATH, "%s.csv" % uuid.uuid4())
with(path, 'w') as fd:
csvbuffer.seek(0)
shutil.copyfileobj(csvbuffer, fd)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
csvbuffer.seek(0)
response.write(csvbuffer)
return response
I am quite sure this not the most optimized way to do it, but at least it should works.
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