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
) 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
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.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('/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:
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) VALUES (%s,%s,%s,%s)",(_title,_description,blog_user_id,now,))
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 = 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']}
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/userHome.htmlBinding retrieved data to html via JQuery templates
url for uquery templates https://github.com/BorisMoore/jquery-tmpl
http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js
bind data inside the ul with class list-group
//templates/userHome.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Flask Add Edit Delete with Jquery ajax, 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) {
// Parse the received JSON string
var data = JSON.parse(res);
//Populate the Pop up
$('#editTitle').val(data[0]['Title']);
$('#editDescription').val(data[0]['Description']);
// Trigger the Pop Up
$('#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">
<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>
<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>
</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>
templates/error.html
//templates/error.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Unauthorized Access</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>
</head>
<body>
<div class="container">
<div class="header">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation" class="active"><a href="/">Home</a></li>
<li role="presentation"><a href="/login">Sign In</a></li>
<li role="presentation"><a href="/signUp">Sign Up</a></li>
</ul>
</nav>
<img src="/static/images/Flask_Icon.png" alt="Flask_Icon.png"/ >
</div>
<div class="jumbotron">
<h1>{{error}}</h1>
</div>
<footer class="footer">
<p>©tutorial101.blogspot.com</p>
</footer>
</div>
</body>
</html>
templates/addBlog.html
//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>
</head>
<body>
<div class="container">
<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 class="form-horizontal" method="post" action="/addBlog">
<fieldset>
<legend>Create Your Blog</legend>
{% if error %}
<div class="alert alert-danger">{{error}}</div>
{% endif %}
<div class="form-group">
<label class="col-md-4 control-label" for="txtTitle">Title</label>
<div class="col-md-4">
<input id="txtTitle" name="inputTitle" type="text" placeholder="placeholder" class="form-control input-md">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="txtPost">Post</label>
<div class="col-md-4">
<textarea class="form-control" id="txtPost" name="inputDescription" ></textarea>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="singlebutton"></label>
<div class="col-md-4">
<input id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit" value="Publish" />
</div>
</div>
</fieldset>
</form>
</section>
<footer class="footer">
<p>©tutorial101.blogspot.com</p>
</footer>
</div>
</body>
</html>
