Created On: June 08, 2021, Last Updated On: May 14, 2022
By Ozzie Ghani3 new
Source Code: https://github.com/Ozzie6935/datatables_001
Steps
# Prepare virtual environment
python3 -m venv venv
cd venv
source bin/activate
# Clone
git clone git@github.com:Ozzie6935/datatables_001.git
# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt
# Run App
python app.py
# Load Users
https://example.com/load_users/<num>
https://example.com/load_users/200
requirement.text
Flask==1.0.3
Flask-SQLAlchemy==2.4.0
SQLAlchemy==1.3.6
requests
app.py
from flask import Flask, request, flash, url_for, redirect, render_template, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CsrfProtect
import requests
import random
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////Users/osmanghani/venv/datatables/db.db'
app.config['SECRET_KEY'] = 'thisissecret'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
CsrfProtect(app)
class STUDENTS(db.Model):
__tablename__ = 'students'
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(100))
city = db.Column(db.String(100))
active = db.Column('is_active', db.Boolean(), nullable=False,
server_default='0')
def __init__(self, **kwargs):
# Call Flask-SQLAlchemy's constructor.
super(STUDENTS, self).__init__(**kwargs)
@classmethod
def find_student_by_id(cls, student_id):
return STUDENTS.query.filter(STUDENTS.id == student_id).first()
def getRandomFromList(l):
"""
Provides renadom pick from provided list
"""
random_index = random.randint(0,len(l)-1)
return l[random_index]
def get_user_data():
"""
:Example Data return
: you can also use endpoints
{"results":[{"gender":"female","name":{"title":"Mrs","first":"Marianne","last":"Gauthier"},"location":{"street":{"number":20,"name":"Lake of Bays Road"},"city":"Grand Falls","state":"Prince Edward Island","country":"Canada","postcode":"G0C 2L7","coordinates":{"latitude":"-60.4553","longitude":"98.2136"},"timezone":{"offset":"+3:00","description":"Baghdad, Riyadh, Moscow, St. Petersburg"}},"email":"marianne.gauthier@example.com","login":{"uuid":"c5a8096c-14b0-429c-8c00-079882df3c7d","username":"beautifulbear505","password":"4444","salt":"qSclKVdW","md5":"1457a6c328661877ea661bfcf7b4290d","sha1":"772b1e3cb9409c44f5f92a0a6713a5a1e70e0ab6","sha256":"03448b2ee5ca69dd633a80d95daf4c7e84a5683c0dd63849a43a1b33614dfc19"},"dob":{"date":"1978-01-16T23:57:41.491Z","age":43},"registered":{"date":"2011-05-31T18:43:06.163Z","age":10},"phone":"189-284-8036","cell":"844-527-4846","id":{"name":"","value":null},"picture":{"large":"https://randomuser.me/api/portraits/women/49.jpg","medium":"https://randomuser.me/api/portraits/med/women/49.jpg","thumbnail":"https://randomuser.me/api/portraits/thumb/women/49.jpg"},"nat":"CA"}],"info":{"seed":"bfbf78ad0d65075e","results":1,"page":1,"version":"1.3"}}
"""
r = requests.get('https://randomuser.me/api/', timeout=2.50)
if r.status_code == 200:
return r.json()
return r.status_code
def to_bool(s):
if isinstance(s, str):
if s.lower() == 'true':
return True
elif s.lower() == 'false':
return False
else:
raise ValueError # evil ValueError that doesn't tell you what the wrong value was
elif isinstance(s, bool):
return bool(s)
elif s == 1:
return True
elif s == 0:
return False
else:
raise ValueError
@app.route('/')
def index():
print(get_user_data())
return render_template('index.html', students = STUDENTS.query.all() )
# https://example.com/load_data/200
@app.route('/load_data', defaults={'num': 10})
@app.route('/load_data/<int:num>')
def load_data(num):
for i in range(int(num)):
d = get_user_data()
fname = d['results'][0]['name']['first']
lname = d['results'][0]['name']['last']
city = d['results'][0]['location']['city']
name = f"{fname} {lname}"
data = {
"name": name,
"city": city,
"active": getRandomFromList([True, False])
}
d = STUDENTS(**data)
db.session.add(d)
db.session.commit()
return f"{num} recored added successfully"
@app.route('/update_student', methods=['GET', 'POST', 'DELETE', 'PUT'])
def update_student():
jsonData = request.get_json()
data = request.json
id = request.form['pk']
key = request.form['name']
value = request.form['value']
## if field holds boolean values, converst string values to bool
if key.lower() in ['active']:
value = to_bool(value)
# update database
s = STUDENTS.find_student_by_id(student_id=id)
setattr(s, key, value)
db.session.add(s)
db.session.commit()
# print("=>",id, request.form, key, value, type(value))
# for k,v in request.form.items():
# print(k, v)
return jsonify(id=id)
if __name__ == '__main__':
db.create_all()
app.run(debug = True)
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="{% block meta_description %}{% endblock %}">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="author" content="Osman Ghani">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap4.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.25/js/dataTables.bootstrap4.min.js"></script>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap-editable.css')}}">
<script src="{{ url_for('static', filename='js/bootstrap-editable.js')}}"></script>
<script type="text/javascript">
var csrftoken = $('meta[name=csrf-token]').attr('content');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
});
</script>
</head>
<body>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">DataTable</div>
<div class="panel-body">
<div class="table-responsive">
<table id="sample_data" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>City</th>
<th>Active</th>
</tr>
</thead>
<tbody>
{% for s in students %}
<tr>
<td data-pk="{{s.id}}">{{s.id}}</td>
<td data-name="name" class="name" data-type="text" data-pk="{{s.id}}">{{s.name}}</td>
<td data-name="city" class="city" data-type="text" data-pk="{{s.id}}">{{s.city}}</td>
<td data-name="active" class="active" data-type="text" data-pk="{{s.id}}">{{s.active}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<br />
<br />
</body>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
var dataTable = $('#sample_data').DataTable();
$('#sample_data').editable({
container: 'body',
selector: 'td.city',
url: '/update_student',
title: 'city',
type: 'POST',
validate: function(value) {
if ($.trim(value) == '') {
return 'This field is required';
}
}
});
$('#sample_data').editable({
container: 'body',
selector: 'td.active',
url: '/update_student',
title: 'active',
type: 'POST',
validate: function(value) {
if ($.trim(value) == '') {
return 'This field is required';
}
}
});
});
</script>
</html>