Flask Jquery ajax upload image with blueimp jQuery-File-Upload, jQuery Templates and MySQLdb Database
CREATE TABLE `tbl_blog` (
`blog_id` int(11) NOT NULL,
`blog_title` varchar(200) NOT NULL,
`blog_description` text NOT NULL,
`blog_user_id` int(11) NOT NULL,
`blog_date` datetime NOT NULL,
`blog_file_path` varchar(200) NOT NULL,
`blog_accomplished` int(11) NOT NULL,
`blog_private` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
#app.py from flask import Flask, render_template, json, request, redirect, session, jsonify from flask_mysqldb import MySQL,MySQLdb #pip install flask-mysqldb https://github.com/alexferl/flask-mysqldb from datetime import datetime import os import uuid app = Flask(__name__) app.secret_key = "caircocoders-ednalan-2020" app.config['MYSQL_HOST'] = 'localhost' app.config['MYSQL_USER'] = 'root' app.config['MYSQL_PASSWORD'] = '' app.config['MYSQL_DB'] = 'flaskdb' app.config['MYSQL_CURSORCLASS'] = 'DictCursor' mysql = MySQL(app) app.config['UPLOAD_FOLDER'] = 'static/Uploads' #templates/static/Uploads/ @app.route('/') def main(): return redirect('/userHome') @app.route('/userHome') def userHome(): session['sessionusername'] = "cairocoders@gmail.com" print(session.get('sessionusername')) if session.get('sessionusername'): return render_template('userHome.html') else: return render_template('error.html',error = 'Unauthorized Access') @app.route('/upload', methods=['GET', 'POST']) def upload(): if request.method == 'POST': file = request.files['file'] extension = os.path.splitext(file.filename)[1] f_name = str(uuid.uuid4()) + extension file.save(os.path.join(app.config['UPLOAD_FOLDER'], f_name)) return json.dumps({'filename':f_name}) @app.route('/addBlog', methods=['GET', 'POST']) def addBlog(): now = datetime.now() print("now =", now) if request.method == 'POST': _title = request.form['inputTitle'] _description = request.form['inputDescription'] _user = session.get('sessionusername') # validate the received values if _title and _description: if request.form.get('filePath') is None: _filePath = '' else: _filePath = request.form.get('filePath') if request.form.get('private') is None: _private = 0 else: _private = 1 if request.form.get('done') is None: _done = 0 else: _done = 1 cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor) result = cur.execute("SELECT * FROM users WHERE email = %s", [_user]) print(result) if result > 0: data = cur.fetchone() blog_user_id = data['id'] cur.execute("INSERT INTO tbl_blog (blog_title, blog_description, blog_user_id, blog_date, blog_file_path, blog_accomplished, blog_private) VALUES (%s,%s,%s,%s,%s,%s,%s)",(_title,_description,blog_user_id,now,_filePath,_private,_done,)) mysql.connection.commit() cur.close() return redirect('/userHome') else: error = 'Invalid login' return render_template('addBlog.html', error=error) else: error = 'Enter the required fields' return render_template('addBlog.html', error=error) return render_template('addBlog.html') @app.route('/getBlog') def getBlog(): if session.get('sessionusername'): _user = '12' cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor) result = cur.execute("SELECT * FROM tbl_blog WHERE blog_user_id = %s", [_user]) blogs = cur.fetchall() blogs_dict = [] for blog in blogs: blog_dict = { 'Id': blog['blog_id'], 'Title': blog['blog_title'], 'Description': blog['blog_description'], 'Date': blog['blog_date']} blogs_dict.append(blog_dict) return json.dumps(blogs_dict) else: print("error getblog") return render_template('error.html', error = 'Unauthorized Access') @app.route('/getBlogById',methods=['GET', 'POST']) def getBlogById(): if session.get('sessionusername'): _id = request.form['id'] cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor) result = cur.execute("SELECT * FROM tbl_blog WHERE blog_id = %s", [_id]) blogs = cur.fetchall() blogs_dict = [] for blog in blogs: blog_dict = { 'Id': blog['blog_id'], 'Title': blog['blog_title'], 'Description': blog['blog_description'], 'FilePath': blog['blog_file_path'], 'Done': blog['blog_accomplished'], 'Private': blog['blog_private']} blogs_dict.append(blog_dict) return json.dumps(blogs_dict) else: return render_template('error.html', error = 'Unauthorized Access') @app.route('/updateBlog', methods=['POST']) def updateBlog(): if session.get('sessionusername'): _title = request.form['title'] _description = request.form['description'] _blog_id = request.form['id'] cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor) cur.execute(""" UPDATE tbl_blog SET blog_title = %s, blog_description = %s WHERE blog_id = %s """, (_title, _description, _blog_id)) mysql.connection.commit() cur.close() return json.dumps({'status':'OK'}) else: return render_template('error.html', error = 'Unauthorized Access') @app.route('/deleteBlog',methods=['POST']) def deleteBlog(): if session.get('sessionusername'): _id = request.form['id'] _user = session.get('user') cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor) cur.execute('DELETE FROM tbl_blog WHERE blog_id = {0}'.format(_id)) mysql.connection.commit() cur.close() return json.dumps({'status':'OK'}) else: return render_template('error.html', error = 'Unauthorized Access') if __name__ == '__main__': app.run(debug=True)templates/addBlog.html
File upload via blueimp jQuery-File-Upload
https://github.com/blueimp/jQuery-File-Upload
Extract the source and add the following script references to addBlog.html
src="/static/js/jquery.fileupload.js
src="/static/js/jquery.fileupload-process.js
src="/static/js/jquery.fileupload-ui.js
//templates/addBlog.html <!DOCTYPE html> <html lang="en"> <head> <title>Add Blog</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" /> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="/static/js/jquery.ui.widget.js"></script> <script type="text/javascript" src="/static/js/jquery.fileupload.js"></script> <script type="text/javascript" src="/static/js/jquery.fileupload-process.js"></script> <script type="text/javascript" src="/static/js/jquery.fileupload-ui.js"></script> <script> $(function(){ $('#fileupload').fileupload({ url: 'upload', dataType: 'json', add: function (e, data) { data.submit(); }, success:function(response,status) { console.log(response.filename); var filePath = 'static/Uploads/' + response.filename; $('#imgUpload').attr('src',filePath); $('#filePath').val(filePath); console.log('success'); }, error:function(error){ console.log(error); } }); }) </script> <style> .btn-file { position: relative; overflow: hidden; } .btn-file input[type=file] { position: absolute; top: 0; right: 0; min-width: 100%; font-size: 100px; text-align: right; filter: alpha(opacity=0); opacity: 0; outline: none; background: white; cursor: inherit; display: block; } </style> </head> <body> <div class="container" style="padding:20px;"> <div class="header"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation" class="active"><a href="/userHome">Dashboard</a></li> <li role="presentation"><a href="/addBlog">Add Blog</a></li> <li role="presentation"><a href="/logout">Log Out</a></li> </ul> </nav> <img src="/static/images/Flask_Icon.png" alt="Flask_Icon.png"/ > </div> <section> <form role="form" method="post" action="/addBlog"> <legend>Create Your Blog Post</legend> <div class="form-group"> <label for="txtTitle">Title</label> <input id="txtTitle" name="inputTitle" type="text" placeholder="placeholder" class="form-control input-md"> </div> <div class="form-group"> <label for="txtPost">Description</label> <textarea class="form-control" id="txtPost" name="inputDescription"></textarea> </div> <div class="form-group"> <label for="txtPost">Photos</label> <div class="input-group"> <span class="input-group-btn"> <span class="btn btn-primary btn-file"> Browse… <input type="file" id="fileupload" name="file" multiple> </span> </span> <div class="pull-right"> <img id="imgUpload" style="width: 140px; height: 140px;" class="img-thumbnail"><input type="hidden" name="filePath" id="filePath"></input> </div> </div> </div> <div class="form-group"> <label>Mark this as private and not visible to others.</label> <br/> <input type="checkbox" name="private"> Mark as Private <span class="glyphicon glyphicon-lock" aria-hidden="true"></span> </div> <div class="form-group"> <label>Have you already accomplished this?</label> <br/> <input type="checkbox" name="done"> Mark as Done <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> </div> <div class="form-group"> <p class="text-center"> <input id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit" value="Publish" /> </p> </div> </form> </section> <footer class="footer"> <p>©tutorial101.blogspot.com</p> </footer> </div> </body> </html>templates/userHome.html
//templates/userHome.html <!DOCTYPE html> <html lang="en"> <head> <title>Flask Jquery ajax upload image with blueimp jQuery-File-Upload, jQuery Templates and MySQLdb Database</title> <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script> <script> $(function(){ $('#btnUpdate').click(function(){ $.ajax({ url : '/updateBlog', data : {title:$('#editTitle').val(),description:$('#editDescription').val(),id:localStorage.getItem('editId')}, type : 'POST', success: function(res){ $('#editModal').modal('hide'); // Re populate the grid GetBlogs(); }, error: function(error){ console.log(error); } }); }); }); function GetBlogs(){ $.ajax({ url : '/getBlog', type : 'GET', success: function(res){ var blogObj = JSON.parse(res); $('#ulist').empty(); $('#listTemplate').tmpl(blogObj).appendTo('#ulist'); }, error: function(error){ console.log(error); } }); } // get blog posts from db when the user signed in $(function() { $.ajax({ url: '/getBlog', type: 'GET', success: function(res) { // Parse the JSON response var blogObj = JSON.parse(res); // Append to the template $('#listTemplate').tmpl(blogObj).appendTo('#ulist'); }, error: function(error) { console.log(error); } }); }); function Edit(elm) { localStorage.setItem('editId',$(elm).attr('data-id')); $.ajax({ url: '/getBlogById', data: { id: $(elm).attr('data-id') }, type: 'POST', success: function(res) { var data = JSON.parse(res); console.log(data); $('#editTitle').val(data[0]['Title']); $('#editDescription').val(data[0]['Description']); $('#imgUpload').attr('src',data[0]['FilePath']); if(data[0]['Private']=="1"){ $('#chkPrivate').attr('checked','checked'); } if(data[0]['Done']=="1"){ $('#chkDone').attr('checked','checked'); } $('#editModal').modal('show'); }, error: function(error) { console.log(error); } }); } function ConfirmDelete(elm){ localStorage.setItem('deleteId',$(elm).attr('data-id')); $('#deleteModal').modal('show'); } function Delete(){ $.ajax({ url : '/deleteBlog', data : {id:localStorage.getItem('deleteId')}, type : 'POST', success: function(res){ var result = JSON.parse(res); if(result.status == 'OK'){ $('#deleteModal').modal('hide'); GetBlogs(); } else{ alert(result.status); } }, error: function(error){ console.log(error); } }); } </script> <style> .trash { color: rgb(209, 91, 71); } .panel-body .checkbox { display: inline-block; margin: 0px; } .list-group { margin-bottom: 0px; } </style> </head> <body> <div class="container" style="padding:20px;"> <div class="header"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation" class="active"><a href="/userHome">Dashboard</a></li> <li role="presentation"><a href="/addBlog">Add Blog</a></li> <li role="presentation"><a href="/logout">Log Out</a></li> </ul> </nav> <img src="/static/images/Flask_Icon.png" alt="Flask_Icon.png"/ > </div> <p><h4>Flask Jquery ajax upload image with blueimp jQuery-File-Upload, jQuery Templates and MySQLdb Database</h4></p> <script id="listTemplate" type="text/x-jQuery-tmpl"> <li class="list-group-item"> <div class="checkbox"> <label> ${Title} </label> </div> <div class="pull-right action-buttons"> <a data-id=${Id} onclick="Edit(this)"><span class="glyphicon glyphicon-pencil"></span></a> <a data-id=${Id} onclick="ConfirmDelete(this)"><span class="glyphicon glyphicon-trash"></span></a> </div> </li> </script> <div class="row"> <div class="col-md-12"> <div class="panel-body"> <ul id="ulist" class="list-group"> </ul> </div> </div> </div> <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> <h4 class="modal-title" id="editModalLabel">Update Blog</h4> </div> <div class="modal-body"> <form role="form"> <div class="form-group"> <label for="recipient-name" class="control-label">Title:</label> <input type="text" class="form-control" id="editTitle"> </div> <div class="form-group"> <label for="message-text" class="control-label">Description:</label> <textarea class="form-control" id="editDescription"></textarea> </div> <div class="form-group"> <label for="txtPost">Photos</label> <div class="input-group"> <span class="input-group-btn"> <span class="btn btn-primary btn-file"> Browse… <input type="file" id="fileupload" name="file" multiple> </span> </span> <div class="pull-right"> <img id="imgUpload" style="width: 140px; height: 140px;" class="img-thumbnail"><input type="hidden" name="filePath" id="filePath"></input> </div> </div> </div> <div class="form-group"> <label>Mark this as private and not visible to others.</label><br/> <input id="chkPrivate" name="private" type="checkbox"> Mark as Private <span class="glyphicon glyphicon-lock" aria-hidden="true"></span> </div> <div class="form-group"> <label>Have you already accomplished this?</label><br/> <input id="chkDone" name="done" type="checkbox"> Mark as Done <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button id="btnUpdate" type="button" class="btn btn-primary">Update</button> </div> </div> </div> </div> <div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header" style="text-align:center;"> <h4 class="modal-title" style="color:red;" id="deleteModalLabel">You are going to Delete this forever !!</h4> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-primary" onclick="Delete()">Delete</button> </div> </div> </div> </div> <footer class="footer"> <p>©tutorial101.blogspot.com</p> </footer> </div> </body> </html>