Im trying to create a movie DB for a school project and I am getting a '400' after submitting the form.
The use of this form is to add Movies to your DB with a description, titel, year and picture(Url to DB) as of now.
routes.py:
#login_required
#app.route('/upMovie', methods=['GET'])
def movieup():
return render_template('upload.html', MovieUploadForm=MovieUploadForm())
#login_required
#app.route('/upMovie', methods=['POST'])
def movieup_validate():
upload_form = MovieUploadForm()
if upload_form.validate_on_submit():
if Movie.query.filter_by(title=upload_form.title.data).first() is not None:
return 'Movie already exists.Back'
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(upload_form.filename.file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
upload_form.filename.file.save(file_path)
movie = Movie(
title=upload_form.title.data,
info=upload_form.info.data,
year=upload_form.year.data,
filename=file_path,
rating=5
)
db.session.add(movie)
db.session.commit()
return redirect(url_for('uploaded_file', filename=filename))
return 'Registration of movie successful.<br/>Home'
else:
upload_form.flash_form_errors()
return render_template('errors.html')
forms.py:
class MovieUploadForm(StandardForm):
title = StringField('Title', validators=[InputRequired(), length(1, 80)])
info = TextAreaField('Info', validators=[length(1, 2000)])
year = DateField('YYYY/MM/DD', format='%Y/%m/%d')
filename = FileField('File URL')
def flash_form_errors(self):
for field, errors in self.errors.items():
for error in errors:
flash("<strong>Error in field: %s</strong> - %s" % (getattr(self, field).label.text, error))
funtions.py
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
So I experimentent around for a while and found a working solution.
The changes I made in routes.py
if upload_form.validate_on_submit():
if upload_form.filename.data.filename is not "":
filename = secure_filename(upload_form.filename.data.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
# file_path = "imdb/static/pic/" + filename
upload_form.filename.data.save(file_path)
movie = Movie(
title=upload_form.title.data,
info=upload_form.info.data,
year=upload_form.year.data,
filename=file_path if upload_form.filename.data else None,
rating=5
)
db.session.add(movie)
db.session.commit()
return 'Registration of movie successful.<br/>Home'
As we are getting our date from our wtforms, we don't need to file = request.files['file'] as the object we are getting is empty.
in forms.py
class MovieUploadForm(StandardForm):
title = StringField('Title', validators=[InputRequired(), length(1, 80)])
info = TextAreaField('Info', validators=[length(1, 2000)])
year = DateField('YYYY/MM/DD', format='%Y/%m/%d')
filename = FileField('File URL', validators=[FileAllowed(['jpg', 'png', 'jpeg'], 'Images only!')])
def validate(self):
v = Form.validate(self)
if not v:
return False
if Movie.query.filter_by(title=self.title.data).first() is not None:
self.title.errors.append("Movie already exists!")
return False
else:
return True
I changed them accordingly, with allowed file endings and also added a Validation for duplicates.
With this code everything seems to work just fine.
Related
I have an Issue trying to Bind my PostForm with an Image Uploading Ability for a Post Made, However there is a functional Profile picture coding which accepts images and save the name to the data base and to avoid error, it adds uuid1 to the image name which is saved on the data base and the image itself is saved in the static folder, image section where it is called upon when needed, all part of the UserForm, but for the PostForm, the method is the same, but instead of a profile picture, it is a post image which should appear there and it keeps giving me interface error, however if the image is excluded, the Post is added to the Database successfully, please I need your help to know what is going wrong, Here is the Code:
#app.route('/add-post', methods=['GET', 'POST'])
def add_post():
form = PostForm()
if form.validate_on_submit():
if request.files['post_image']:
post_image = request.files['post_image']
post_filename = secure_filename(post_image.filename)
post_name = str(uuid.uuid1()) + "_" + post_filename
saver = request.files['post_image']
post_image = str(uuid.uuid1()) + "_" + post_filename
try:
db.session.commit()
saver.save(os.path.join(app.config['UPLOAD_FOLDER'], post_name))
except:
flash("Error! Looks Like There Was a Problem... Try Again!")
else:
db.session.commit()
poster = current_user.id
post = Posts(title=form.title.data, post_image=form.post_image.data, content=form.content.data, poster_id=poster, slug=form.slug.data)
form.title.data = ''
form.content.data = ''
form.slug.data = ''
form.post_image.data = ''
db.session.add(post)
db.session.commit()
flash("Blog Post Submitted Successfully !")
return render_template("add_post.html", form=form)
After weeks of trying and having errors, I finally got the hang of it... I will post the answer below:
#app.route('/add-post', methods=['GET', 'POST'])
def add_post():
form = PostForm()
if form.validate_on_submit():
poster = current_user.id
post = Posts(title=form.title.data, content=form.content.data, file=form.file.data, poster_id=poster, slug=form.slug.data)
if request.files['file']:
upload.file = request.files['file']
filename = secure_filename(upload.file.filename)
file_name = str(uuid.uuid1()) + "_" + filename
saver = request.files['file']
post.file = file_name
try:
db.session.add(post)
db.session.commit()
saver.save(os.path.join(app.config['UPLOAD_FOLDER'], file_name))
flash("User Updated Successfully !")
return render_template("add_post.html",
form=form)
except:
flash("Error! Looks Like There Was a Problem... Try Again!")
return render_template("add_post.html",
form=form)
else:
db.session.add(post)
db.session.commit()
flash("User Updated Successfully !")
return render_template("add_post.html",
form=form)
form.title.data = ''
form.content.data = ''
form.slug.data = ''
db.session.add(post)
db.session.commit()
return render_template("add_post.html",
form=form,
id = id or 1)
so i have this two views, one used to display information and one that returns a file responde. I am trying to download a pdf file using the information on the first view:
#login_required()
def detail(request, location_name):
if request.method == "POST":
return search_in_employees(request)
current = CurrentInfo()
pdf_data = current.detail_employees_by_location(location_name) # this gives me the list of people
context = {
'present': current.detail_employees_by_location(location_name),
'location': location_name,
}
print('Data: -------------->', pdf_data)
return render(request, 'user_area/detail.html', context)
and my second view just formats it as a pdf:
#login_required()
def download_pdf(request):
buf = io.BytesIO()
canv = canvas.Canvas(buf, pagesize=letter, bottomup=0)
textob = canv.beginText()
textob.setTextOrigin(inch, inch)
textob.setFont("Helvetica", 14)
lines = [
"Line 1 ",
"Line 2 ",
"Line 3 ",
"Line 4 ",
]
for line in lines:
textob.textLine(line)
canv.drawText(textob)
canv.showPage()
canv.save()
buf.seek(0)
return FileResponse(buf, as_attachment=True, filename='employees.pdf')
Right now the PDF file only contains dummy data, but how can i pass pdf_data from the first view to the second?
I would suggest creating a function either inside your views.py or inside a helpers.py file in your module:
def get_pdf_data(location_name):
current = CurrentInfo()
pdf_data = current.detail_employees_by_location(location_name)
return pdf_data
Then your first view would look like:
#login_required()
def detail(request, location_name):
if request.method == "POST":
return search_in_employees(request)
pdf_data = get_pdf_data(location_name)
context = {
'present': pdf_data,
'location': location_name,
}
print('Data: -------------->', pdf_data)
return render(request, 'user_area/detail.html', context)
And your second view can use this new function but only if you send the location_name to the view same as the first view
#login_required()
def download_pdf(request, location_name):
pdf_data = get_pdf_data(location_name)
buf = io.BytesIO()
canv = canvas.Canvas(buf, pagesize=letter, bottomup=0)
textob = canv.beginText()
textob.setTextOrigin(inch, inch)
textob.setFont("Helvetica", 14)
for line in pdf_data:
textob.textLine(line)
canv.drawText(textob)
canv.showPage()
canv.save()
buf.seek(0)
return FileResponse(buf, as_attachment=True, filename='employees.pdf')
I suspect it has something got to do with refresh token. Could not understand how to use it by the docs. Can I know the exact code how to use it?
The access token is created during login:
#app.route('/login', methods=['POST','GET'])
def login():
username = request.form["email"]
password = request.form["password"]
my_token_expiry_time = datetime.timedelta(seconds=60)
segments = 0
access_token = None
if request.method == 'POST':
result_set = authenticate_user(username, password)
if result_set:
ss1 = select([nsettings]).\
where(nsettings.c.mattribute == 'my_jwt_expiry_time_min')
rss1 = g.conn.execute(ss1)
if rss1.rowcount > 0:
for r in rss1:
my_token_expiry_time = datetime.timedelta(seconds=
(int(r[nsettings.c.mvalue])* 60))
else:
my_token_expiry_time = datetime.timedelta(
seconds=(2 * 60 *60)) # 2 hours
#print result_set, 'result_set result_set'
session['email'] = result_set['email']
access_token = create_access_token(
identity=username, expires_delta=my_token_expiry_time)
user_dict = result_set
if user_dict:
session['email'] = user_dict['email']
session['id'] = result_set['id']
# users and related views
session['access_token'] = access_token
print access_token, 'aaaaaaaaaaa'
return jsonify({
'email': session['email'],
'user_id': result_set['id'],
'access_token': access_token,
'id': session['id'],
}), 200
else:
return jsonify({'message': "Invalid credentials, retry"}), 401
return "True"
The flask api call to upload:
#app.route('/rt/api/v1.0/issues/<int:issue_id>/documents', methods=['POST'])
#jwt_required
def rt_doc_upload(issue_id):
'''
Upload documents for a rt ticket.
'''
# Iterate through the list of files, we don't care about the
# attribute name. We consider only the first file and ignore the
# rest.
if 'id' in session:
uploader = "3"
minternal_only = True
bool_internal_update = False
msg_str = None
for attr, document in request.files.iteritems():
trans = g.conn.begin()
try:
orig_filename = document.filename
filename, upload_folder = check_or_insert_document(
orig_filename, uploader)
new_doc = add_doc(orig_filename, filename)
print orig_filename, 'origooooo'
ins = archival_docs.insert().values(new_doc)
rs = g.conn.execute(ins)
doc_id = rs.inserted_primary_key[0]
filename = (str(doc_id) + '_' + orig_filename)
stmt = archival_docs.update().values(stored_name=filename).\
where(archival_docs.c.id == doc_id)
g.conn.execute(stmt)
document.save(os.path.join(upload_folder, filename))
mattach_doc_id = genUrl(doc_id)
trans.commit()
return jsonify(
{'issue_doc_id': rs.inserted_primary_key[0]}), 201
except Exception, e:
print e
trans.rollback()
return jsonify({'message': "Did not find any file"}), 400
return jsonify({'message': "UNAUTHORIZED"}), 401
When used with runserver and on commenting the jwt_required decorator I am able to upload and download files
Using sqlalchemy core, python and flask. The api call to upload worked for more than a month, but suddenly stopped working now
I have a small Flask project that gets some inputs from the user and extracts some data from the database based on the input back to the user and returns an output file.
The code works just fine if the file format is csv. However when the file format is xls, I see the output being generated but the flask app does not return the file.
Edited:
Given below is the code for views.py
#app.route('/data', methods=['GET','POST'])
def data():
form = DataForm()
if form.validate_on_submit():
name = form.name.data
start_date = form.start_date_field.data
end_date = form.end_date_field.data
file_extension = form.file_extension_field.data
rep_func(name=name, start_date=start_date, end_date=end_date, exten=file_extension)
current_directory = path.abspath(path.join(__file__, ".."))
base = os.path.join(current_directory, 'files')
if file_extension == 'csv':
data = pd.read_csv(base + f'/final_output/{name}_{end_date}.{file_extension}', sep=r',(?!\s|\Z)', engine='python')
resp = make_response(data.to_csv(index=False))
resp.headers["Content-Disposition"] = f'attachment; filename={name}_{end_date}.{file_extension}'
resp.headers["Content-Type"] = "text/csv"
elif file_extension == 'xls':
data = pd.read_excel(base + f'/final_output/{name}_{end_date}.{file_extension}')
resp = make_response(data.to_excel(index=False))
resp.headers["Content-Disposition"] = f'attachment; filename={name}_{end_date}.{file_extension}'
resp.headers["Content-Type"] = "application/vnd.ms-excel"
return resp
return render_template('file.html', form=form)
Could anyone advise on where am I going wrong with this. Thanks
Here's my code
#login_required
def upload(request):
form_type = ''
transcript = Transcript()
transcript.file_path = ''
if request.method == 'POST':
if 'file_form' in request.POST:
file_form = FileForm(request.POST, request.FILES)
if file_form.is_valid():
path = handle_uploaded_file(request.FILES['file'], request.user)
transcript.file_path = path
transcript.user = request.user
export_form = InfoForm()
form_type = 'info_form'
elif 'info_form' in request.POST:
if transcript.file_path:
info_form = InfoForm(request.POST)
if info_form.is_valid():
transcript.user = request.user
transcript.title = info_form.cleaned_data.get('title')
transcript.instructions = info_form.cleaned_data.get('instructions')
transcript.save()
return HttpResponseRedirect('thanks')
else:
raise ValueError('Transcript object has no file path attribute')
else:
export_form = FileForm()
form_type = 'file_form'
return render(request, 'transcription/upload.html', {'form': export_form, 'form_type': form_type})
always, the file-form is called before the info-form, so the code in the if statement
if transcript.file_path:
#...
should always execute. But the ValueError always gets raised, meaning transcript.file_path is reset. How does this happen, and how can it be fixed?
file_form and info_form in POST are names of the different submit buttons, so I know which form I am dealing with.
def handle_uploaded_file(file, user):
id = randint(0, 10000)
user_dir = settings.MEDIA_ROOT + '/' + str(user.id).replace(".", "") + '/'
path = user_dir + file.name.replace(".mp3", str(id) + ".mp3")
if not os.path.exists(user_dir):
os.makedirs(user_dir)
with open(path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
file = File(destination)
info = {'path': path, 'file': file}
return path
So it was a rookie mistake.
I didn't know that during each post request the whole view gets called again.
So I just initialized my variables
form_type = ''
transcript = Transcript()
transcript.file_path = ''
outside the view and voila!