Create folders in flask - python

I want to create folders using flask . I Google for this a lot but didn't find any help. Evey search shows me the folder structure of flask but I want to know how can I create folders using code.
Actually I want to create folders for every user at register time.So suggest me a way how can I create a simple empty folder at particular path in flask.

Use os.mkdir or os.makedirs according to your need.
import os
os.makedirs('/path/to/directory')

create folders for every user at register time.
You can override the default constructor of sqlalchemy orm like this and do custom stuff
inside the function. Here is semi working code.
from app import db
import os
class User(db.Model):
# ...
folder = db.Column(db.String(80), unique=True, nullable=False)
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
# do custom stuff call folder create method here
self.create_folder()
# method to create folder
def create_folder(self):
#give path to location where you want to create folder
path = "my path where i want to create folder"
os.mkdir(path)
#update some property in User database
self.folder = "path to my user folder"

from flask import Flask, request
import os
app = Flask(__name__)
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.config['UPLOAD_FOLDER'] = 'static/users/'
#app.route('/register', methods=["POST", "GET"])
def register():
username = request.form.get("username")
if request.method == "POST":
username = username.strip().capitalize()
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
os.mkdir(user_folder)
return f"folder is created under the name {username} and the full path is {user_folder}"
return """
<form method="post" action="/register">
<input type="text" name="username" required>
<button type="submit" >Submit</button>
</form>
"""

Related

How to prevent uploaded files from having the same name Flask Python

I am trying to build a website in python using flask that takes file uploads and saves them to a folder (called uploads). However, when two files with the same name are uploaded, the first one is overwritten by the last one. How can I prevent this in a way that means that I don't lose any files? Would adding a timestamp to the filename help or would there still be an issue if two files are uploaded at the same time?
Thanks!
Filesystem
FlaskProject:
├───static
├───templates
├───uploads
└───app.py
Html
{%extends "base.html" %}
{%block content%}
<p>
<h2>Upload Below!</h2>
<div></div>
<form action = "http://localhost:5000/upload_complete" method = "POST"
enctype = "multipart/form-data">
<input type = "file" name = "file" />
<input type = "submit"/>
</form>
{% endblock %}
Python
from flask import Flask, redirect, url_for, render_template, request
from werkzeug.utils import secure_filename
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = "D:/Me/FlaskProject/uploads"
#app.route('/upload')
def upload():
return render_template("upload.html", page="Upload Images")
#app.route('/upload_complete', methods = ['GET', 'POST'])
def upload_complete():
if request.method == 'POST':
f = request.files['file']
f.save(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(f.filename)))
return redirect(url_for('upload_complete'))
return render_template("upload_complete.html", page="Upload Complete")
if __name__ == '__main__':
app.debug = True
app.run()
app.run(debug = True)
(upload_complete.html is just a thank you screen)
You can generate an uuid and update the filename with it.
You can generate uuid like this,
import uuid
... your code ..
hash_value = uuid.uuid4().hex
f.save(os.path.join(app.config['UPLOAD_FOLDER'], hash_value + secure_filename(f.filename)))

Bad request error when chosing file on server with form

from flask.ext.wtf import Form
from flask import send_from_directory
from wtforms import StringField, BooleanField
from wtforms import SelectField
import os
from os import listdir
from os.path import isfile, join
crewPath = ("/myproject/app/static/Crews")
filenamesCrew = [f for f in listdir(crewPath) if isfile(join(crewPath,f)) ]
class userInput(Form):
json_fileCrew = SelectField(u"json_fileCrew", choices=[(f, f) for f in filenamesCrew])
def get_data(self):
json = send_from_directory (crewPath, self.json_fileCrew.data)
return json
#app.route('/CastCrew', methods=['GET', 'POST'])
def castCrew():
form = userInput(request.form["crewYear"])
return render_template('CastCrew.html', title = 'Cast Crew View', form = form)
#app.route("/data", methods=['GET', 'POST']) #the javascript will call this
def data():
form = userInput(request.form["crewYear"])
return form.get_data()
<form class = "form" action="/data" method="post" name="crewYear">
{{ form.hidden_tag() }} <!--CSFR config -->
<p>Please choose a year:<br>
{{ form.json_fileCrew }}<br></p>
<p><input type="submit" value="Submit"></p>
</form>
I am getting a "Bad Request" error when I submit the form. How do I fix this?
The layout of project files:
---app
---views.py
---forms.py
---static
---Crews (about 100 .json files in this folder)
---1981.json
---css
---js
---templates
---base.html
---crew.html
I modified code according answer below but I still get a 404 Not Found Error when I click the button.
The immediate problem is that you're passing the value of request.form["crewYear"] to your form, rather than the entire request.form.
There are a lot of minor problems with your code. You don't need to use send_from_directory, since there's a more specific function to send from the static directory. You should populate the select field in the form init, otherwise it will not reflect any files added after the app starts. You should use app.static_folder rather than hard coding the path. You have two routes that do the same thing.
import os
from flask import current_app
from flask_wtf import Form
from wtforms.field import SelectField
class CrewForm(Form):
filename = SelectField()
def __init__(self, *args, **kwargs):
root = os.path.join(current_app.static_folder, 'Crews')
choices = [(f, f) for f in os.listdir(root) if os.path.isfile(os.path.join(root, f))]
self.filename.kwargs['choices'] = choices
super(CrewForm, self).__init__(*args, **kwargs)
#app.route('/crew', methods=['GET', 'POST'])
def crew():
form = CrewForm()
if form.validate_on_submit():
return current_app.send_static_file('Crews/{}'.format(form.filename.data))
return render_template('crew.html', form=form)
<form method="post">
{{ form.hidden_tag() }}
{{ form.filename }}
<input type="submit" value="Get Data"/>
</form>
Consider reading the Flask tutorial and Flask-WTF docs, as they clearly explain how to use forms. Reading PEP 8 would also be beneficial, as your code style is very inconsistent.

Flask and sqlalchemy: Get uploaded file using path stored on database

I'm using flask and sqlalchemy and I'm having issues regarding file uploading.
I'm uploading the file with a form and storing the URL to the DB, so I can display it inside on the page.
Here's the form's code:
boxart = request.files['boxart']
if boxart:
filename = secure_filename(boxart.filename)
boxart_path = os.path.join(app.config['UPLOAD_FOLDER']+"boxart/", filename)
boxart.save(boxart_path)
game_son.boxart = boxart_path
db.session.add(game_son)
db.session.commit()
So I go to my template and I can print the content of game_son.boxart and there is the full path to the file. If I click on the link, I can access, but the image will not display inside tag...
I tried getting it on the template by using:
<img src="{{ game_son.boxart_url() }}" />
Inside the model, I defined a boxart_url method, in case I need to parse the string before sending it
class Game_son(db.Model):
__searchable__ = ['version_name']
son_id = db.Column(db.Integer, primary_key=True)
version_name = db.Column(db.String(128), index=True, unique=False)
son_timestamp = db.Column(db.DateTime)
dad = db.Column(db.Integer, db.ForeignKey('game_dad.id'))
console = db.Column(db.Integer, db.ForeignKey('platform.id'))
boxart = db.Column(db.String(256))
thumbnail = db.Column(db.String(256))
genre = db.Column(db.String(32))
subgenre = db.Column(db.String(32))
def boxart_url(self):
return self.boxart
def __repr__(self):
return '<Game %r>: %r' % (self.version_name, self.dad)
The page's view just send the entire object (game) to the page.
The url that is arriving on the page is:
/home/removed_my_pc_user/app/media/boxart/image.jpg
Edit:
I just remembered that I'm using a virtual environment on the project.
Is it related to chmod?
Thanks in advance!!
Well, It's strange but I will answer my own question.
The solution is simple, I chose to store only the file names inside the database.
Then I created a route to a view that will return the file using the send_from_directory function from flask.ext.uploads
#app.route('/boxart/<filename>')
def uploaded_boxart(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],filename)
So, inside the template we can use the url_for() function to load the file, sending as a parameter the filename stored inside the database.
<img src="{{ url_for('uploaded_boxart', filename = game_son.boxart)}}" />
Also, I think that one of my mistakes was putting the media/ folder inside the app/ folder, and not inside the root directory. So I also reconfigured the UPLOAD_FOLDER in app.config.

django how to upload folder

I know how to upload multiple files through django, but I have a problem when uploading a folder if there are subfolders in it. The django can't receive subfolders. I found the reason, because browser use '.' to represent a folder, but django can't parse it then stop parsing. Is there an elegant way to fix it?
python code:
def uploader_single(request):
data = {}
if request.method == 'POST':
if True:
for afile in request.FILES.getlist('file'):
new_file = UploadFileSingle(file = afile)
new_file.save()
return HttpResponseRedirect('')
else:
print "form is not valid"
return HttpResponseRedirect('')
else:
print 'not post'
Python code:
class UploadFileSingle(models.Model):
file = models.FileField(upload_to='files/%Y/%m/%d', models.FilePath)
uploaded_at = models.DateTimeField(auto_now_add=True)
models.FilePathField.recursive = True
models.FilePathField.allow_folders = True
updated_at = models.DateTimeField(auto_now=True)
def some_folder = FilePathField(path='some_path', recursive=True, allow_files=True, allow_folders=True,)'
HTML code:
<input type="file" name="file" multiple = "true" webkitdirectory="true" directory = "true"/>
There is newer topic which asks the same question and I have tried to answer:
Django directory upload get sub-directory names
Basically it is the default behavior of Django if you want to have different behavior you need to write your own upload handlers
I came up with easy solution for this problem.
You could get folder name via html and javascript in frontend
pass it as a value to hidden form field
in backend you can create a directory with that name
and upload files in this directory.
HTML
<input type="hidden" name="dir_name" id="id_dir_name">
<input type="file" name="file" onchange="selectFolder(event)" webkitdirectory="" multiple="" required="" directory="" id="id_file">
JS
function selectFolder(e) {
var theFiles = e.target.files;
var relativePath = theFiles[0].webkitRelativePath;
var folder = relativePath.split("/");
$("#" + id).val(folder[0]);
}
views
directory_name = form.cleaned_data['dir_name']
os.mkdir(os.path.join(settings.MEDIA_ROOT, directory_name))
handle_uploaded_file(request.FILES['file'], directory_name)
you can use django filer
rerfer:https://github.com/stefanfoulis/django-filer

Storing a string from a textbox to the Google App Engine Datastore

Is it possible to create a textbox in HTML, type a string into it, click a "save" button, store that information onto a GAE datastore model and have the text stay displayed in the textbox and saved in the datastore?
The HTML is on a separate file, just rendered through my main.py file using
class MainPage(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
What I tried for my problem is this:
class equipmentBox(db.Model):
equipCode = db.StringProperty()
class equipmentBoxGet(webapp.RequestHandler):
def post(self):
I think this will help, i have modified default guestbook app for you. Usual way of doing is having html files separately and using templates to render it. Here everything is just embedded into the controller itself
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class EquipmentBox(db.Model):
equipCode = db.StringProperty()
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
equips = db.GqlQuery("SELECT * FROM EquipmentBox")
for equip in equips:
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(equip.equipCode))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/post" method="post">
<div><input type="text" name="equip_code" /></div>
<div><input type="submit" value="post equipcode"></div>
</form>
</body>
</html>""")
class EquipBox(webapp.RequestHandler):
def post(self):
equip = EquipmentBox()
equip.equipCode = self.request.get('equip_code')
equip.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/post', EquipBox)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
The best way to build this sort of interface, where the user "saves" data on the page without the page changing, is to use AJAX calls.
While a full explanation of how AJAX works is probably beyond the scope of an answer here, the basic idea is that you have a Javascript onclick event attached to your Save button, which sends the contents of your textbox via a POST request to the server. See the link above for a tutorial.

Categories