Skip to content

Instantly share code, notes, and snippets.

@LexPanov

LexPanov/app.py Secret

Last active May 24, 2022 20:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LexPanov/8cb89c6515946fa0def2147656ed9ed9 to your computer and use it in GitHub Desktop.
Save LexPanov/8cb89c6515946fa0def2147656ed9ed9 to your computer and use it in GitHub Desktop.
put html files in folder "templates"
import os
from flask import (Flask, render_template, request)
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#from werkzeug.middleware.proxy_fix import ProxyFix
#app.wsgi_app = ProxyFix(app.wsgi_app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////'+os.getcwd()+'/test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy()
db.init_app(app)
class Expert(db.Model):
__tablename__ = 'experts'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), index=True)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
}
@staticmethod
def generate_fake(count=100):
from random import choices
names=['Alex', 'Alice', 'Bob','John']
for i in range(count):
u = Expert(name=choices(names, weights=[1,2,3,4], k=1)[0])
db.session.add(u)
db.session.commit()
with app.app_context():
db.drop_all()
db.create_all()
Expert.generate_fake()
db.session.commit()
@app.route('/api/data', methods=['POST'])
def data():
query = Expert.query
# SearchPanes
searchpanes = {'options':{}}
sp_fields=['id', 'name']
for sp_field in sp_fields:
# init SearchPanes
names = [row[0] for row in db.session.query(getattr(Expert, sp_field).distinct()).all()]
searchpanes['options'][sp_field]=[]
for name in names:
name_d = {"label": name,
"total": query.filter(getattr(Expert, sp_field)==name).count(),
"value": name,
"count": query.filter(getattr(Expert, sp_field)==name).count()}
searchpanes['options'][sp_field].append(name_d)
# SearchPanes filter
if request.form.get(f'searchPanes[{sp_field}][0]'):
sp_filter = []
i = 0
while True:
col_name = request.form.get(f'searchPanes[{sp_field}][{i}]')
if col_name is None:
break
sp_filter.append(col_name)
i += 1
query = query.filter(getattr(Expert, sp_field).in_(sp_filter))
# search
search = request.form.get('search[value]')
if search:
query = query.filter(db.or_(
Expert.id.like(f'%{search}%'),
Expert.name.like(f'%{search}%')))
total_filtered = query.count()
# sorting
order = []
i = 0
while True:
col_index = request.form.get(f'order[{i}][column]')
if col_index is None:
break
col_name = request.form.get(f'columns[{col_index}][data]')
descending = request.form.get(f'order[{i}][dir]') == 'desc'
col = getattr(Expert, col_name)
if descending:
col = col.desc()
order.append(col)
i += 1
if order:
query = query.order_by(*order)
# pagination
start = request.form.get('start', type=int)
length = request.form.get('length', type=int)
query = query.offset(start).limit(length)
# response
return {
'data': [expert.to_dict() for expert in query],
'recordsFiltered': total_filtered,
'recordsTotal': Expert.query.count(),
'draw': request.form.get('draw', type=int),
'searchPanes': searchpanes
}
@app.route('/')
def client():
return render_template('table_client.html')
@app.route('/server')
def server():
return render_template('table_server.html')
if __name__ == '__main__':
app.run(host='0.0.0.0')
Click==7.0
Flask-SQLAlchemy==2.4.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
SQLAlchemy==1.3.8
Werkzeug==0.15.5
{% block content %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/css/dataTables.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/searchpanes/css/searchPanes.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/select/css/select.semanticui.css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/searchpanes/js/dataTables.searchPanes.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/js/dataTables.semanticui.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/searchpanes/js/searchPanes.semanticui.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/select/js/dataTables.select.js"></script>
{#
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.3/css/dataTables.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/searchpanes/1.4.0/css/searchPanes.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.3.3/css/select.semanticui.css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/dataTables.semanticui.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/searchpanes/1.4.0/js/dataTables.searchPanes.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/searchpanes/1.4.0/js/searchPanes.semanticui.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/select/1.3.3/js/dataTables.select.js"></script>
#}
<div class="ui centered grid">
<div class="row">
<a class="ui basic compact button" href="{{ url_for('server') }}">
Change to serverSide: true
</a>
</div>
<div class="eight wide column">
<table id="data" class="ui searchable sortable unstackable selectable celled table">
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#data').DataTable({
dom: 'Plfrtip',
ajax: {
url:"{{ url_for('data') }}",
type: "POST"
},
columns: [
{data: 'id'},
{data: 'name'}
],
columnDefs:[{
searchPanes:{
show: true,
},
targets: [0,1]
}],
serverSide: false,
select: true
});
});
</script>
{% endblock %}
{% block content %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/css/dataTables.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/searchpanes/css/searchPanes.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://nightly.datatables.net/select/css/select.semanticui.css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/searchpanes/js/dataTables.searchPanes.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/js/dataTables.semanticui.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/searchpanes/js/searchPanes.semanticui.js"></script>
<script type="text/javascript" src="https://nightly.datatables.net/select/js/dataTables.select.js"></script>
{#
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.3/css/dataTables.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/searchpanes/1.4.0/css/searchPanes.semanticui.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.3.3/css/select.semanticui.css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/dataTables.semanticui.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/searchpanes/1.4.0/js/dataTables.searchPanes.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/searchpanes/1.4.0/js/searchPanes.semanticui.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/select/1.3.3/js/dataTables.select.js"></script>
#}
<div class="ui centered grid">
<div class="row">
<a class="ui basic compact button" href="{{ url_for('client') }}">
Change to serverSide: false
</a>
</div>
<div class="eight wide column">
<table id="data" class="ui searchable sortable unstackable selectable celled table">
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#data').DataTable({
dom: 'Plfrtip',
ajax: {
url:"{{ url_for('data') }}",
type: "POST"
},
columns: [
{data: 'id'},
{data: 'name'}
],
columnDefs:[{
searchPanes:{
show: true,
},
targets: [0,1]
}],
serverSide: true,
select: true
});
});
</script>
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment