article

Thursday, October 15, 2020

Flask Jquery ajax upload image with blueimp jQuery-File-Upload, jQuery Templates and MySQLdb Database

 

Flask Jquery ajax upload image with blueimp jQuery-File-Upload, jQuery Templates and MySQLdb Database

Database Table
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
#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>

Related Post