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
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 am trying to save a file and do something to it a from in an html file, I am not using django forms but I am using django for backend and I don't need a database since I don't want to keep any of the files. I tried what the django documentation has instructed.
html file
<input type="file" id="face_files" name="face_files" multiple >
view.py
def index(request):
if request.method == "GET":
return render(request, 'index.html')
if request.method == "POST":
form = InputForm(request)
call_form_function(form)
return render(request, 'index.html')
Inputform.py
class InputForm():
def __init__(self, request):
self.face_files = request.FILES.getlist('face_files')
# print('face_files= ', self.face_files)
self.face_name = request.POST.get('face_name')
# print('face_name= ', self.face_name)
def save_files(self):
import os
self.delete_temp()
folder = os.path.dirname(__file__) + '/static/temp/'+self.face_name
try:
os.mkdir(folder)
counter=1
for file in self.face_files:
# print(file)
destination=open(folder +"/face"+str(counter)+".jpg", 'wb+')
for chunk in file.chunks():
destination.write(chunk)
destination.close()
counter+=1
except:
with open(console_html_path, "w+") as f:
f.write(traceback.format_exc())
traceback.print_exc()
return folder
def do_function(self):
folder_path = self.save_files()
function(args, folder_path)
def call_form_function(form):
import threading
t1 = threading.Thread(target=form.do_function)
t1.start()
But I get the error
lib/python3.7/site-packages/django/core/files/uploadedfile.py", line 91, in chunks
self.file.seek(0)
ValueError: I/O operation on closed file.
what am I doing wrong?
You can create a separate function to handle the uploaded file.
def handle_uploaded_files(f):
with open(f'uploaded/folder/path/{f.name}', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
I made a youtube video download Manager. It download a video but i am facing one issue when i download same video, it doesn't download it again. how can i download it again with same title like pic.png and send pic1.png. How can i do that?
def Download(self):
video_url = self.lineEdit.text()
save_location = self.lineEdit_2.text()
if video_url == '' or save_location == '':
QMessageBox.warning(self, "Data Error", "Provide a Valid Video URL or save Location")
else:
video = pafy.new(video_url)
video_stream = video.streams
video_quality = self.comboBox.currentIndex()
download = video_stream[video_quality].download(filepath=save_location, callback=self.Handel_Progress, )
Ok, this one is interesting.
The real problem begins here.
download = video_stream[video_quality].download(filepath=save_location, callback=self.Handel_Progress, )
Here, you are calling download function of video_stream object which takes filepath as an argument for file location but does not take the filename, because, obviously, the file would be saved with the actual name.
Root Cause of your problem:
If you look into the definition of download function, you would find that if a file exists with the same name, it would not download the file at all.
Now comes the part, how do you make sure it downloads, no matter what:
There are two things you need to do:
Check if a file with same name exists or not, and if does, then add 1 in the end of the file name just before the extension. So if abc.mp4 exists, then save abc1.mp4.
[I will tell you how to handle the scenario when abc.mp4, abc1.mp4 and so on exists, but for now, let's get back to the problem.]
How to pass the file name (abc1.mp4) to the download method?
Following piece of code would handle both.
I have added comments for your understanding.
import os
import re
import pafy
from pafy.util import xenc
# this function is used by pafy to generate file name while saving,
# so im using the same function to get the file name which I will use to check
# if file exists or not
# DO NOT CHANGE IT
def generate_filename(title, extension):
max_length = 251
""" Generate filename. """
ok = re.compile(r'[^/]')
if os.name == "nt":
ok = re.compile(r'[^\\/:*?"<>|]')
filename = "".join(x if ok.match(x) else "_" for x in title)
if max_length:
max_length = max_length + 1 + len(extension)
if len(filename) > max_length:
filename = filename[:max_length - 3] + '...'
filename += "." + extension
return xenc(filename)
def get_file_name_for_saving(save_location, full_name):
file_path_with_name = os.path.join(save_location, full_name)
# file exists, add 1 in the end, otherwise return filename as it is
if os.path.exists(file_path_with_name):
split = file_path_with_name.split(".")
file_path_with_name = ".".join(split[:-1]) + "1." + split[-1]
return file_path_with_name
def Download(self):
video_url = self.lineEdit.text()
save_location = self.lineEdit_2.text()
if video_url == '' or save_location == '':
QMessageBox.warning(self, "Data Error", "Provide a Valid Video URL or save Location")
else:
# video file
video = pafy.new(video_url)
# available video streams
video_stream = video.streams
video_quality = self.comboBox.currentIndex()
# video title/name
video_name = video.title
# take out the extension of the file from video stream
extension = video_stream[video_quality].extension
# fullname with extension
full_name = generate_filename(video_name, extension)
final_path_with_file_name = get_file_name_for_saving(save_location, full_name)
download = video_stream[video_quality].download(filepath=final_path_with_file_name,
callback=self.Handel_Progress, )
Let me know if you face any issues.
i have this code, first i get the image from a input and then i create a copy in folder in this case 'tareas', then i need to print the name of that image, i can create the copy successfully but i can't get the name of the copy.
if request.method == "POST":
uploaded_file = request.FILES['imagen']
fs = FileSystemStorage()
fs.save(uploaded_file.name, uploaded_file)
caminodelarchivo = "C:/Users/Usuario/Documents/Django/Proyecto/imagenes/tareas"
files = glob.glob(caminodelarchivo)
ultimoarchivo = max(files, key=os.path.getctime)
print ("El nombre es: ", ultimoarchivo)
In your case filename stored in uploaded_file.name why you don't use it?
After reading some texts regarding creation of files under python, i decided to create this class which creates a new file on a directory, and creating a backup on the other directory if the file already exists (and if it's older than x hours )
The main reason i opened this question is to know if this is a correct way to write a class using try/except correctly, because actually i'm getting a little confused about the preference of using try/except instead if/elses.
Bellow, the working example:
import os
import datetime
class CreateXML():
def __init__(self, path, filename):
self.path = path
self.bkp_path = "%s\\backup" % path
self.filename = filename
self.bkp_file = "%s.previous" % filename
self.create_check = datetime.datetime.now()-datetime.timedelta(hours=-8)
#staticmethod
def create_dir(path):
try:
os.makedirs(path)
return True
except:
return False
#staticmethod
def file_check(file):
try:
open(file)
return True
except:
return False
def create_file(self, target_dir, target_file):
try:
target = "%s\\%s" % (target_dir, target_file)
open(target, 'w')
except:
return False
def start_creation(self):
try:
# Check if file exists
if self.file_check("%s\\%s" % (self.path, self.filename)):
self.create_dir(self.bkp_path)
creation = os.path.getmtime("%s\\%s" % (self.path, self.filename))
fcdata = datetime.datetime.fromtimestamp(creation)
# File exists and its older than 8 hours
if fcdata < self.create_check:
bkp_file_path = "%s\\%s " % (self.bkp_path, self.bkp_file)
new_file_path = "%s\\%s " % (self.path, self.filename)
# If backup file exists, erase current backup file
# Move existing file to backup and create new file.
if self.file_check("%s\\%s" % (self.bkp_path, self.bkp_file)):
os.remove(bkp_file_path)
os.rename(new_file_path, bkp_file_path)
self.create_file(self.bkp_path, self.bkp_file)
#No backup file, create new one.
else:
self.create_file(self.bkp_path, self.bkp_file)
else:
# Fresh creation
self.create_dir(self.path)
self.create_file(self.path, self.filename)
except OSError, e:
print e
if __name__ == '__main__':
path = 'c:\\tempdata'
filename = 'somefile.txt'
cx = CreateXML(path, filename)
cx.start_creation()
So, basically the real question here is:
-With the example above, the usage of try/except is correct?
-It's correct to perform the validations using try/except to check if file or directory allready exists? instead using a simplified version like this one:
import os
# Simple method of doing it
path = 'c:\\tempdata'
filename = 'somefile.txt'
bkp_path = 'c:\\tempdata\\backup'
bkp_file = 'somefile.txt.bkp'
new_file_path = "%s\\%s" % (path, filename)
bkp_file_path = "%s\\%s" % (bkp_path, bkp_file)
if not os.path.exists(path):
print "create path"
os.makedirs(bkp_path)
if not os.path.isfile(new_file_path):
print "create new file"
open(new_file_path, 'w')
else:
print"file exists, moving to backup folder"
#check if backup file exists
if not os.path.isfile(bkp_file_path):
print "New backup file created"
open(bkp_file_path, 'w')
else:
print "backup exists, removing backup, backup the current, and creating newfile"
os.remove(bkp_file_path)
os.rename(new_file_path, bkp_file_path)
open(bkp_file_path, 'w')
-If the usage of try/except is correct, its recomended write an a big class to create a file if it's possible to write a short version of it?
Please do not close this tread, since i'm really confused about what is the "most correct pythonic way to do it".
Thanks in advance.