fix with view_context
This commit is contained in:
parent
958cde4baf
commit
cf4ffc861a
@ -23,7 +23,6 @@ from sqlalchemy.orm.collections import InstrumentedList
|
|||||||
from sqlalchemy_utils import Choice
|
from sqlalchemy_utils import Choice
|
||||||
from tww.lib import solve_query, resolve_timezone, dt_tz_translation, time_ago
|
from tww.lib import solve_query, resolve_timezone, dt_tz_translation, time_ago
|
||||||
from whooshalchemy import IndexService
|
from whooshalchemy import IndexService
|
||||||
from oshipka.search import add_to_index, remove_from_index, query_index
|
|
||||||
from oshipka.util.strings import camel_case_to_snake_case
|
from oshipka.util.strings import camel_case_to_snake_case
|
||||||
|
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
@ -221,11 +220,17 @@ def register_filters(app):
|
|||||||
class Proxy(object):
|
class Proxy(object):
|
||||||
def __init__(self, proxied):
|
def __init__(self, proxied):
|
||||||
self.proxied = proxied
|
self.proxied = proxied
|
||||||
|
self.searchables = []
|
||||||
|
|
||||||
|
|
||||||
index_service = Proxy(None)
|
index_service = Proxy(None)
|
||||||
|
|
||||||
|
|
||||||
|
def register_index_svc():
|
||||||
|
for searchable in index_service.searchables:
|
||||||
|
index_service.proxied.register_class(searchable)
|
||||||
|
|
||||||
|
|
||||||
def init_db(app):
|
def init_db(app):
|
||||||
rv = False
|
rv = False
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI
|
app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI
|
||||||
@ -253,6 +258,7 @@ def init_db(app):
|
|||||||
rv = True
|
rv = True
|
||||||
global index_service
|
global index_service
|
||||||
index_service.proxied = IndexService(config=app.config, session=db.session)
|
index_service.proxied = IndexService(config=app.config, session=db.session)
|
||||||
|
register_index_svc()
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
@ -280,46 +286,3 @@ def populate_static(app):
|
|||||||
instance = model(**row)
|
instance = model(**row)
|
||||||
db.session.add(instance)
|
db.session.add(instance)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
class SearchableMixin(object):
|
|
||||||
@classmethod
|
|
||||||
def search(cls, expression, page, per_page):
|
|
||||||
ids, total = query_index(cls.__tablename__, expression, page, per_page)
|
|
||||||
if total == 0:
|
|
||||||
return cls.query.filter_by(id=0), 0
|
|
||||||
when = []
|
|
||||||
for i in range(len(ids)):
|
|
||||||
when.append((ids[i], i))
|
|
||||||
return cls.query.filter(cls.id.in_(ids)).order_by(
|
|
||||||
db.case(when, value=cls.id)), total
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def before_commit(cls, session):
|
|
||||||
session._changes = {
|
|
||||||
'add': list(session.new),
|
|
||||||
'update': list(session.dirty),
|
|
||||||
'delete': list(session.deleted)
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def after_commit(cls, session):
|
|
||||||
for obj in session._changes['add']:
|
|
||||||
if isinstance(obj, SearchableMixin):
|
|
||||||
add_to_index(obj.__tablename__, obj)
|
|
||||||
for obj in session._changes['update']:
|
|
||||||
if isinstance(obj, SearchableMixin):
|
|
||||||
add_to_index(obj.__tablename__, obj)
|
|
||||||
for obj in session._changes['delete']:
|
|
||||||
if isinstance(obj, SearchableMixin):
|
|
||||||
remove_from_index(obj.__tablename__, obj)
|
|
||||||
session._changes = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def reindex(cls):
|
|
||||||
for obj in cls.query:
|
|
||||||
add_to_index(cls.__tablename__, obj)
|
|
||||||
|
|
||||||
|
|
||||||
db.event.listen(db.session, 'before_commit', SearchableMixin.before_commit)
|
|
||||||
db.event.listen(db.session, 'after_commit', SearchableMixin.after_commit)
|
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
from flask import current_app
|
|
||||||
|
|
||||||
|
|
||||||
def add_to_index(index, model):
|
|
||||||
if not hasattr(current_app, 'elasticsearch'):
|
|
||||||
return
|
|
||||||
payload = {}
|
|
||||||
for field in model.__searchable__:
|
|
||||||
payload[field] = getattr(model, field)
|
|
||||||
current_app.elasticsearch.index(index=index, id=model.id, body=payload)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_from_index(index, model):
|
|
||||||
if not hasattr(current_app, 'elasticsearch'):
|
|
||||||
return
|
|
||||||
current_app.elasticsearch.delete(index=index, id=model.id)
|
|
||||||
|
|
||||||
|
|
||||||
def query_index(index, query, page, per_page):
|
|
||||||
if not hasattr(current_app, 'elasticsearch'):
|
|
||||||
return [], 0
|
|
||||||
search = current_app.elasticsearch.search(
|
|
||||||
index=index,
|
|
||||||
body={'query': {'multi_match': {'query': query, 'fields': ['*']}},
|
|
||||||
'from': (page - 1) * per_page, 'size': per_page})
|
|
||||||
ids = [int(hit['_id']) for hit in search['hits']['hits']]
|
|
||||||
return ids, search['hits']['total']['value']
|
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Delete {{ model_name }}:{{ instance.id }} ?</h1>
|
<h1>Delete {{ model_view.model_name }}:{{ instance.id }} ?</h1>
|
||||||
<form action="{{ url_for('delete_' + model_name, uuid=instance.uuid) }}" method="post">
|
<form action="{{ url_for('delete_' + model_view.model_name, uuid=instance.uuid) }}" method="post">
|
||||||
<input type="hidden" value="{{ request.args.next or url_for('list_' + model_name) }}" name="_next"/>
|
<input type="hidden" value="{{ request.args.next or url_for('list_' + model_view.model_name) }}" name="_next"/>
|
||||||
<input type="submit"/>
|
<input type="submit"/>
|
||||||
</form>
|
</form>
|
||||||
<a href="{{ request.args.next }}">Back</a>
|
<a href="{{ request.args.next }}">Back</a>
|
||||||
|
@ -1,185 +1,173 @@
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
from uuid import uuid4
|
|
||||||
|
|
||||||
import inflect
|
import inflect
|
||||||
from flask import flash, render_template, redirect, request, url_for
|
from flask import flash, render_template, redirect, request, url_for, jsonify
|
||||||
|
|
||||||
from oshipka.persistance import db
|
from oshipka.persistance import db
|
||||||
from oshipka.util.strings import camel_case_to_snake_case
|
from oshipka.util.strings import camel_case_to_snake_case
|
||||||
|
|
||||||
|
|
||||||
def get_instance(model_view, uuid):
|
def default_get_args_func(view_context):
|
||||||
model = model_view.model
|
view_context.serialized_args = request.args
|
||||||
if uuid.isdigit():
|
|
||||||
instance = model.query.filter_by(id=uuid).first()
|
|
||||||
|
def default_get_form_func(vc):
|
||||||
|
vc.redirect_next = request.form.get('_next')
|
||||||
|
vc.serialized_args = dict(filter(lambda k: not k[0].startswith("_"), dict(request.form).items()))
|
||||||
|
to_delete = []
|
||||||
|
for key, value in vc.serialized_args.items():
|
||||||
|
if key.endswith('_id'):
|
||||||
|
if value in ['']:
|
||||||
|
to_delete.append(key)
|
||||||
|
else:
|
||||||
|
vc.serialized_args[key] = int(value)
|
||||||
|
for key in to_delete:
|
||||||
|
del vc.serialized_args[key]
|
||||||
|
|
||||||
|
|
||||||
|
def default_jsonify_func(vc):
|
||||||
|
if type(vc.instances) is list:
|
||||||
|
return jsonify([instance.serialize() for instance in vc.instances])
|
||||||
|
return jsonify(vc.instances.serialize())
|
||||||
|
|
||||||
|
|
||||||
|
def default_redirect_func(vc):
|
||||||
|
return redirect(vc.redirect_next or request.referrer or url_for('home'))
|
||||||
|
|
||||||
|
|
||||||
|
def default_get_func(vc):
|
||||||
|
model = vc.model_view.model
|
||||||
|
uuid = vc.url_args.get('uuid')
|
||||||
|
if uuid and vc.url_args.get('uuid').isdigit():
|
||||||
|
vc.instances = model.query.filter_by(id=uuid).all()
|
||||||
else:
|
else:
|
||||||
instance = model.query.filter_by(uuid=uuid).first()
|
vc.instances = model.query.filter_by(uuid=uuid).all()
|
||||||
if not instance:
|
if not vc.instances:
|
||||||
flash("No {}:{}".format(model_view.model_name, uuid))
|
flash("No {}:{}".format(vc.model_view.model_name, uuid))
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
def list_view(model_view, template_func=None, template_ctx_func=None, args_process_func=None,
|
def default_list_args_get_func(vc):
|
||||||
list_func=None, post_list_func=None, **kwargs):
|
vc.serialized_args = request.args
|
||||||
def inner():
|
|
||||||
serialized_args = request.args
|
|
||||||
serialized_args = args_process_func(serialized_args) if args_process_func else serialized_args
|
|
||||||
instances = None
|
|
||||||
if list_func is not None:
|
|
||||||
instances = list_func(model_view, serialized_args)
|
|
||||||
if instances is None:
|
|
||||||
instances = model_view.model.query.all()
|
|
||||||
if post_list_func is not None:
|
|
||||||
instances = post_list_func(instances)
|
|
||||||
template = template_func(instances) if template_func else None
|
|
||||||
if not template:
|
|
||||||
template = "{}/list.html".format(model_view.model_name)
|
|
||||||
template_ctx = template_ctx_func(instances) if template_ctx_func else {}
|
|
||||||
return render_template(template, instances=instances, **template_ctx)
|
|
||||||
|
|
||||||
return inner
|
|
||||||
|
|
||||||
|
|
||||||
def get_view(model_view, template_func=None, template_ctx_func=None, args_process_func=None,
|
def default_list_func(vc):
|
||||||
get_func=None, post_get_func=None, **kwargs):
|
vc.instances = vc.model_view.model.query.all()
|
||||||
def inner(uuid):
|
|
||||||
serialized_args = request.args
|
|
||||||
serialized_args = args_process_func(serialized_args) if args_process_func else serialized_args
|
|
||||||
instance = None
|
|
||||||
if get_func is not None:
|
|
||||||
instance = get_func(model_view, uuid, serialized_args)
|
|
||||||
if instance is not None:
|
|
||||||
instance = instance[0]
|
|
||||||
if instance is None:
|
|
||||||
instance = get_instance(model_view, uuid)
|
|
||||||
if post_get_func is not None:
|
|
||||||
instance = post_get_func(instance)
|
|
||||||
template = template_func(instance) if template_func else None
|
|
||||||
if not template:
|
|
||||||
template = "{}/get.html".format(model_view.model_name)
|
|
||||||
template_ctx = template_ctx_func(instance) if template_ctx_func else {}
|
|
||||||
return render_template(template, instance=instance, **template_ctx)
|
|
||||||
|
|
||||||
return inner
|
|
||||||
|
|
||||||
|
|
||||||
def serialize_form():
|
def default_search_func(vc):
|
||||||
return dict(filter(lambda k: not k[0].startswith("__"), dict(request.form).items()))
|
q = vc.serialized_args.get('q')
|
||||||
|
if hasattr(vc.model_view.model, 'search_query'):
|
||||||
|
vc.instances = vc.model_view.model.search_query("{q}".format(q=q)).all()
|
||||||
|
|
||||||
|
|
||||||
def update_view(model_view, template_func=None, template_ctx_func=None, args_process_func=None,
|
def default_create_func(vc):
|
||||||
should_update_func=None, post_add=None, post_commit=None, **kwargs):
|
instance = vc.model_view.model(**vc.serialized_args)
|
||||||
def inner(uuid):
|
db.session.add(instance)
|
||||||
instance = get_instance(model_view, uuid)
|
vc.instances = [instance]
|
||||||
if not instance:
|
|
||||||
return redirect(request.referrer or url_for('home'))
|
|
||||||
|
def default_update_func(vc):
|
||||||
|
instance = vc.instances[0]
|
||||||
|
for k, v in vc.serialized_args.items():
|
||||||
|
setattr(instance, k, v)
|
||||||
|
db.session.add(instance)
|
||||||
|
|
||||||
|
|
||||||
|
def default_delete_func(vc):
|
||||||
|
instance = vc.instances[0]
|
||||||
|
db.session.delete(instance)
|
||||||
|
|
||||||
|
|
||||||
|
def default_render_func(vc):
|
||||||
|
if len(vc.instances) == 1:
|
||||||
|
vc.template_ctx['instance'] = vc.instances[0]
|
||||||
|
vc.template_ctx['instances'] = vc.instances
|
||||||
|
vc.template_ctx['model_view'] = vc.model_view
|
||||||
|
return render_template(vc.template, **vc.template_ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def default_commit_func(vc):
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def default_none_func(vc):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ViewContext(object):
|
||||||
|
def __init__(self, args_get_func=None, args_process_func=None,
|
||||||
|
filter_func=None, redirect_func=None,
|
||||||
|
should_execute_func=None, execute_func=None, post_execute_func=None,
|
||||||
|
commit_func=None, post_commit_func=None,
|
||||||
|
jsonify_func=None, render_func=None, template_func=None, template_ctx_func=None,
|
||||||
|
should_redirect_no_instances_func=None,
|
||||||
|
should_redirect_at_end_func=None,
|
||||||
|
json=False, **kwargs):
|
||||||
|
self.args_get_func = args_get_func or default_get_args_func
|
||||||
|
self.args_process_func = args_process_func or default_none_func
|
||||||
|
self.filter_func = filter_func or default_none_func
|
||||||
|
self.should_redirect_no_instances_func = should_redirect_no_instances_func or default_none_func
|
||||||
|
self.redirect_func = redirect_func or default_redirect_func
|
||||||
|
self.should_execute_func = should_execute_func or default_none_func
|
||||||
|
self.execute_func = execute_func or default_none_func
|
||||||
|
self.post_execute_func = post_execute_func or default_none_func
|
||||||
|
self.commit_func = commit_func or default_commit_func
|
||||||
|
self.post_commit_func = post_commit_func or default_none_func
|
||||||
|
self.jsonify_func = jsonify_func or default_jsonify_func
|
||||||
|
self.render_func = render_func or default_render_func
|
||||||
|
self.template_func = template_func or default_none_func
|
||||||
|
self.template_ctx_func = template_ctx_func or default_none_func
|
||||||
|
self.should_redirect_at_end_func = should_redirect_at_end_func or default_none_func
|
||||||
|
self.json = json
|
||||||
|
|
||||||
|
self.serialized_args = {}
|
||||||
|
self.url_args = {}
|
||||||
|
self.instances = []
|
||||||
|
self.should_execute = True
|
||||||
|
self.should_redirect_at_end = True
|
||||||
|
self.template = None
|
||||||
|
self.template_ctx = {}
|
||||||
|
self.model_view = None
|
||||||
|
self.redirect_next = None
|
||||||
|
|
||||||
|
|
||||||
|
def create_view(model_view, view_context, is_json=False, **kwargs):
|
||||||
|
view_context.model_view = model_view
|
||||||
|
|
||||||
|
def return_json_or_template():
|
||||||
|
if is_json:
|
||||||
|
return view_context.jsonify_func(view_context)
|
||||||
|
view_context.template_func(view_context)
|
||||||
|
view_context.template_ctx_func(view_context)
|
||||||
|
return view_context.render_func(view_context)
|
||||||
|
|
||||||
|
def inner(**kwargs):
|
||||||
|
view_context.url_args = kwargs
|
||||||
|
view_context.args_get_func(view_context)
|
||||||
|
view_context.args_process_func(view_context)
|
||||||
|
|
||||||
|
view_context.filter_func(view_context)
|
||||||
|
if not view_context.instances:
|
||||||
|
if view_context.should_redirect_no_instances_func(view_context):
|
||||||
|
return view_context.redirect_func(view_context)
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
template = template_func(instance) if template_func else None
|
return return_json_or_template()
|
||||||
if not template:
|
|
||||||
template = "{}/edit.html".format(model_view.model_name)
|
|
||||||
template_ctx = template_ctx_func(instance) if template_ctx_func else {}
|
|
||||||
return render_template(template, instance=instance, **template_ctx)
|
|
||||||
serialized_form = serialize_form()
|
|
||||||
|
|
||||||
_next = serialized_form.pop('_next') if '_next' in serialized_form else None
|
view_context.should_execute_func(view_context)
|
||||||
serialized_form = args_process_func(serialized_form) if args_process_func else serialized_form
|
if not view_context.should_execute:
|
||||||
if should_update_func is not None:
|
return view_context.redirect_func(view_context)
|
||||||
should_update, msg = should_update_func(instance, serialized_form)
|
|
||||||
else:
|
|
||||||
should_update, msg = True, ""
|
|
||||||
if not should_update:
|
|
||||||
if msg:
|
|
||||||
flash(msg)
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
for k, v in serialized_form.items():
|
|
||||||
setattr(instance, k, v)
|
|
||||||
|
|
||||||
db.session.add(instance)
|
view_context.execute_func(view_context)
|
||||||
if post_add is not None:
|
view_context.post_execute_func(view_context)
|
||||||
post_add(instance)
|
view_context.commit_func(view_context)
|
||||||
|
view_context.post_commit_func(view_context)
|
||||||
|
|
||||||
db.session.commit()
|
view_context.should_redirect_at_end_func(view_context)
|
||||||
if post_commit is not None:
|
if view_context.should_redirect_at_end:
|
||||||
post_commit(instance)
|
return view_context.redirect_func(view_context)
|
||||||
flash("Updated {}:{}".format(model_view.model_name, id))
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
|
|
||||||
return inner
|
return return_json_or_template()
|
||||||
|
|
||||||
|
|
||||||
def create_view(model_view, template_func=None, template_ctx_func=None, args_process_func=None,
|
|
||||||
should_func=None, post_add=None, post_commit=None):
|
|
||||||
def inner():
|
|
||||||
if request.method == "GET":
|
|
||||||
template = template_func() if template_func else None
|
|
||||||
if not template:
|
|
||||||
template = "{}/create.html".format(model_view.model_name)
|
|
||||||
template_ctx = template_ctx_func() if template_ctx_func else {}
|
|
||||||
return render_template(template, **template_ctx)
|
|
||||||
serialized_form = serialize_form()
|
|
||||||
|
|
||||||
_next = serialized_form.pop('_next') if '_next' in serialized_form else None
|
|
||||||
serialized_form = args_process_func(serialized_form) if args_process_func else serialized_form
|
|
||||||
serialized_form['uuid'] = str(uuid4())
|
|
||||||
|
|
||||||
if should_func is not None:
|
|
||||||
should_create, msg = should_func(serialized_form)
|
|
||||||
else:
|
|
||||||
should_create, msg = True, ""
|
|
||||||
if not should_create:
|
|
||||||
if msg:
|
|
||||||
flash(msg)
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
instance = model_view.model(**serialized_form)
|
|
||||||
db.session.add(instance)
|
|
||||||
if post_add is not None:
|
|
||||||
post_add(instance)
|
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
if post_commit is not None:
|
|
||||||
post_commit(instance)
|
|
||||||
flash("Created {}".format(model_view.model_name))
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
|
|
||||||
return inner
|
|
||||||
|
|
||||||
|
|
||||||
def delete_view(model_view, template_func=None, template_ctx_func=None, args_process_func=None,
|
|
||||||
should_func=None, post_delete=None, post_commit=None, **kwargs):
|
|
||||||
def inner(uuid):
|
|
||||||
instance = get_instance(model_view, uuid)
|
|
||||||
if not instance:
|
|
||||||
return redirect(request.referrer or url_for('home'))
|
|
||||||
if request.method == "GET":
|
|
||||||
template = template_func(instance) if template_func else None
|
|
||||||
if not template:
|
|
||||||
template = "delete_instance.html"
|
|
||||||
template_ctx = template_ctx_func(instance) if template_ctx_func else {}
|
|
||||||
return render_template(template,
|
|
||||||
instance=instance,
|
|
||||||
model_name=model_view.model_name,
|
|
||||||
**template_ctx)
|
|
||||||
|
|
||||||
serialized_form = serialize_form()
|
|
||||||
serialized_form = args_process_func(serialized_form) if args_process_func else serialized_form
|
|
||||||
_next = serialized_form.pop('_next') if '_next' in serialized_form else None
|
|
||||||
if should_func is not None:
|
|
||||||
should_delete, msg = should_func(instance, serialized_form)
|
|
||||||
else:
|
|
||||||
should_delete, msg = True, ""
|
|
||||||
if not should_delete:
|
|
||||||
if msg:
|
|
||||||
flash(msg)
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
db.session.delete(instance)
|
|
||||||
if post_delete is not None:
|
|
||||||
post_delete(instance)
|
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
if post_commit is not None:
|
|
||||||
post_commit(instance)
|
|
||||||
flash("Deleted {}:{}".format(model_view.model_name, uuid))
|
|
||||||
return redirect(_next or request.referrer or url_for('home'))
|
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
@ -194,36 +182,71 @@ class ModelView(object):
|
|||||||
self.model_name = camel_case_to_snake_case(model.__name__)
|
self.model_name = camel_case_to_snake_case(model.__name__)
|
||||||
self.model_name_pl = p.plural(self.model_name)
|
self.model_name_pl = p.plural(self.model_name)
|
||||||
|
|
||||||
def register_create(self, **kwargs):
|
def _register_rule(self, url_args, **kwargs):
|
||||||
url = '/{}/create'.format(self.model_name_pl)
|
url = url_args.pop('rule')
|
||||||
self.app.add_url_rule(url, methods=["GET", "POST"],
|
api_url = '/api{}'.format(url)
|
||||||
endpoint='create_{}'.format(self.model_name),
|
endpoint = url_args.pop('endpoint')
|
||||||
view_func=create_view(self, **kwargs))
|
api_endpoint = 'api_{}'.format(endpoint)
|
||||||
|
view_func = url_args.pop('view_func')
|
||||||
def register_list(self, **kwargs):
|
self.app.add_url_rule(rule=url, endpoint=endpoint,
|
||||||
url = '/{}'.format(self.model_name_pl)
|
view_func=view_func(self, **kwargs), **url_args)
|
||||||
self.app.add_url_rule(url,
|
kwargs['is_json'] = True
|
||||||
'list_{}'.format(self.model_name),
|
self.app.add_url_rule(rule=api_url, endpoint=api_endpoint,
|
||||||
list_view(self, **kwargs))
|
view_func=view_func(self, **kwargs), **url_args)
|
||||||
|
|
||||||
def register_get(self, **kwargs):
|
def register_get(self, **kwargs):
|
||||||
url = '/{}/<uuid>'.format(self.model_name_pl)
|
url_args = dict(
|
||||||
|
rule='/{}/<uuid>/get'.format(self.model_name_pl),
|
||||||
|
methods=["GET"],
|
||||||
|
endpoint='get_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
self.app.add_url_rule(url,
|
def register_list(self, **kwargs):
|
||||||
'get_{}'.format(self.model_name),
|
url_args = dict(
|
||||||
get_view(self, **kwargs))
|
rule='/{}/list'.format(self.model_name_pl),
|
||||||
|
methods=["GET"],
|
||||||
|
endpoint='list_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
|
def register_create(self, **kwargs):
|
||||||
|
url_args = dict(
|
||||||
|
rule='/{}/create'.format(self.model_name_pl),
|
||||||
|
methods=["GET", "POST"],
|
||||||
|
endpoint='create_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
def register_update(self, **kwargs):
|
def register_update(self, **kwargs):
|
||||||
url = '/{}/<uuid>/edit'.format(self.model_name_pl)
|
url_args = dict(
|
||||||
self.app.add_url_rule(url, methods=["GET", "POST"],
|
rule='/{}/<uuid>/update'.format(self.model_name_pl),
|
||||||
endpoint='update_{}'.format(self.model_name),
|
methods=["GET", "POST"],
|
||||||
view_func=update_view(self, **kwargs))
|
endpoint='update_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
def register_delete(self, **kwargs):
|
def register_delete(self, **kwargs):
|
||||||
url = '/{}/<uuid>/delete'.format(self.model_name_pl)
|
url_args = dict(
|
||||||
self.app.add_url_rule(url, methods=["GET", "POST"],
|
rule='/{}/<uuid>/delete'.format(self.model_name_pl),
|
||||||
endpoint='delete_{}'.format(self.model_name),
|
methods=["GET", "POST"],
|
||||||
view_func=delete_view(self, **kwargs))
|
endpoint='delete_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
|
def register_search(self, **kwargs):
|
||||||
|
url_args = dict(
|
||||||
|
rule='/{}/search'.format(self.model_name_pl),
|
||||||
|
methods=["GET"],
|
||||||
|
endpoint='search_{}'.format(self.model_name),
|
||||||
|
view_func=create_view,
|
||||||
|
)
|
||||||
|
self._register_rule(url_args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def catch_flash(f):
|
def catch_flash(f):
|
||||||
|
@ -1,109 +1,62 @@
|
|||||||
def get_template_func(instance):
|
from oshipka.webapp.views import ViewContext, default_get_args_func, default_get_func, default_list_func, \
|
||||||
return None
|
default_get_form_func, default_create_func, default_update_func, default_delete_func, default_search_func
|
||||||
|
|
||||||
|
|
||||||
def get_templ_ctx_func(instance):
|
def get_template(vc):
|
||||||
rv = dict()
|
vc.template = "{}/get.html".format(vc.model_view.model_name)
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def get_func(model_view, uuid, serialized_args):
|
def search_template(vc):
|
||||||
"""Should return a list of one element (or [None] if element is none) or None if you want default behaviour"""
|
vc.template = "{}/search.html".format(vc.model_view.model_name)
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def post_get_func(instance):
|
def list_template(vc):
|
||||||
return instance
|
vc.template = "{}/list.html".format(vc.model_view.model_name)
|
||||||
|
|
||||||
|
|
||||||
def list_template_func(instances):
|
def create_template(vc):
|
||||||
return None
|
vc.template = "{}/create.html".format(vc.model_view.model_name)
|
||||||
|
|
||||||
|
|
||||||
def list_templ_ctx_func(instances):
|
def update_template(vc):
|
||||||
rv = dict()
|
vc.template = "{}/update.html".format(vc.model_view.model_name)
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def list_func(model_view, serialized_args):
|
def delete_template(vc):
|
||||||
"""Should return a list elements or None if you want default behaviour"""
|
vc.template = "delete_instance.html".format(vc.model_view.model_name)
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def post_list_func(instances):
|
get_view_context = ViewContext(
|
||||||
return instances
|
filter_func=default_get_func,
|
||||||
|
template_func=get_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
list_view_context = ViewContext(
|
||||||
|
filter_func=default_list_func,
|
||||||
|
template_func=list_template,
|
||||||
|
)
|
||||||
|
|
||||||
def create_template_func():
|
search_view_context = ViewContext(
|
||||||
return None
|
filter_func=default_search_func,
|
||||||
|
template_func=list_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
create_view_context = ViewContext(
|
||||||
|
args_get_func=default_get_form_func,
|
||||||
|
template_func=create_template,
|
||||||
|
execute_func=default_create_func,
|
||||||
|
)
|
||||||
|
|
||||||
def create_templ_ctx_func():
|
update_view_context = ViewContext(
|
||||||
rv = dict()
|
args_get_func=default_get_form_func,
|
||||||
return rv
|
filter_func=default_get_func,
|
||||||
|
template_func=update_template,
|
||||||
|
execute_func=default_update_func,
|
||||||
|
)
|
||||||
|
|
||||||
|
delete_view_context = ViewContext(
|
||||||
def create_args_process_func(serialized_form):
|
args_get_func=default_get_form_func,
|
||||||
return serialized_form
|
filter_func=default_get_func,
|
||||||
|
template_func=delete_template,
|
||||||
|
execute_func=default_delete_func,
|
||||||
def create_should_func(serialized_form):
|
)
|
||||||
return True, ""
|
|
||||||
|
|
||||||
|
|
||||||
def create_post_add_func(instance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def create_post_commit_func(instance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def update_template_func(instance):
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def update_templ_ctx_func(instance):
|
|
||||||
rv = dict()
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def update_args_process_func(serialized_form):
|
|
||||||
return serialized_form
|
|
||||||
|
|
||||||
|
|
||||||
def update_should_func(serialized_form):
|
|
||||||
return True, ""
|
|
||||||
|
|
||||||
|
|
||||||
def update_post_add_func(instance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def update_post_commit_func(instance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def delete_template_func(instance):
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def delete_templ_ctx_func(instance):
|
|
||||||
rv = dict()
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def delete_args_process_func(serialized_form):
|
|
||||||
return serialized_form
|
|
||||||
|
|
||||||
|
|
||||||
def delete_should_func(instance, serialized_form):
|
|
||||||
return True, ""
|
|
||||||
|
|
||||||
|
|
||||||
def delete_post_delete_func(instance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def delete_post_commit_func(instance):
|
|
||||||
pass
|
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
<h2>Create [[ name ]]</h2>
|
|
||||||
<form action="{{ url_for('create_[[ name|camel_to_snake ]]') }}" method="post">
|
<form action="{{ url_for('create_[[ name|camel_to_snake ]]') }}" method="post">
|
||||||
<input type="hidden" name="_next" value="{{ url_for('list_[[ name|camel_to_snake ]]') }}"/>
|
<input type="hidden" name="_next" value="{{ url_for('list_[[ name|camel_to_snake ]]') }}"/>
|
||||||
[%- for column in columns %]
|
[%- for column in columns %]
|
||||||
<label for="input-[[ name|camel_to_snake ]]-[[ column.name ]]">[[ column.name ]]</label>:
|
<label for="input-[[ name|camel_to_snake ]]-[[ column.name ]]">[[ column.name ]]</label>:
|
||||||
<input id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
|
[%- if column.type in ['relationship'] %]
|
||||||
type="text" name="[[ column.name ]]" autocomplete="off"
|
<input id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
|
||||||
/>
|
type="number" name="[[ column.name ]]_id" autocomplete="off"
|
||||||
|
/>
|
||||||
|
[%- else %]
|
||||||
|
<input id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
|
||||||
|
type="text" name="[[ column.name ]]" autocomplete="off"
|
||||||
|
/>
|
||||||
|
[%- endif %]
|
||||||
[%- endfor %]
|
[%- endfor %]
|
||||||
<input type="submit">
|
<input type="submit">
|
||||||
</form>
|
</form>
|
@ -1,3 +0,0 @@
|
|||||||
<h2>{% include "[[ name|camel_to_snake ]]/_title.html" %}</h2>
|
|
||||||
<a href="{{ url_for('update_[[ name|camel_to_snake ]]', uuid=instance.id) }}">edit</a> |
|
|
||||||
<a href="{{ url_for('delete_[[ name|camel_to_snake ]]', uuid=instance.id) }}">delete</a>
|
|
@ -1,6 +1,3 @@
|
|||||||
<h2>[[ name|pluralize ]]</h2>
|
|
||||||
<a href="{{ url_for('create_[[ name|camel_to_snake ]]') }}">Create</a>
|
|
||||||
<br>
|
|
||||||
{% for instance in instances %}
|
{% for instance in instances %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('get_[[ name|camel_to_snake ]]', uuid=instance.id) }}">
|
<a href="{{ url_for('get_[[ name|camel_to_snake ]]', uuid=instance.id) }}">
|
||||||
|
11
vm_gen/templates/html/_search.html
Normal file
11
vm_gen/templates/html/_search.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% for instance in instances %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('get_[[ name|camel_to_snake ]]', uuid=instance.id) }}">
|
||||||
|
{% include "[[ name|camel_to_snake ]]/_title.html" %}</a>
|
||||||
|
|
|
||||||
|
[
|
||||||
|
<a href="{{ url_for('update_[[ name|camel_to_snake ]]', uuid=instance.id) }}">e</a> |
|
||||||
|
<a href="{{ url_for('delete_[[ name|camel_to_snake ]]', uuid=instance.id) }}">x</a>
|
||||||
|
]
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
@ -1,4 +1,3 @@
|
|||||||
<h2>Edit {% include "[[ name|camel_to_snake ]]/_title.html" %}</h2>
|
|
||||||
<form action="{{ url_for('update_[[ name|camel_to_snake ]]', uuid=instance.id) }}" method="post">
|
<form action="{{ url_for('update_[[ name|camel_to_snake ]]', uuid=instance.id) }}" method="post">
|
||||||
<input type="hidden" name="_next" value="{{ url_for('get_[[ name|camel_to_snake ]]', uuid=instance.id) }}"/>
|
<input type="hidden" name="_next" value="{{ url_for('get_[[ name|camel_to_snake ]]', uuid=instance.id) }}"/>
|
||||||
[%- for column in columns %]
|
[%- for column in columns %]
|
@ -1,5 +1,6 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h2>Create [[ name ]]</h2>
|
||||||
{% include "[[ name|camel_to_snake ]]/_create.html" %}
|
{% include "[[ name|camel_to_snake ]]/_create.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,5 +0,0 @@
|
|||||||
{% extends "layout.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% include "[[ name|camel_to_snake ]]/_edit.html" %}
|
|
||||||
{% endblock %}
|
|
@ -1,5 +1,9 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<a href="{{ url_for('list_[[ name|camel_to_snake ]]', uuid=instance.id) }}">list</a> |
|
||||||
|
<h2>{% include "[[ name|camel_to_snake ]]/_title.html" %}</h2>
|
||||||
|
<a href="{{ url_for('update_[[ name|camel_to_snake ]]', uuid=instance.id) }}">edit</a> |
|
||||||
|
<a href="{{ url_for('delete_[[ name|camel_to_snake ]]', uuid=instance.id) }}">delete</a>
|
||||||
{% include "[[ name|camel_to_snake ]]/_get.html" %}
|
{% include "[[ name|camel_to_snake ]]/_get.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,5 +1,8 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h2>[[ name|pluralize ]]</h2>
|
||||||
|
<a href="{{ url_for('create_[[ name|camel_to_snake ]]') }}">Create</a>
|
||||||
|
<br>
|
||||||
{% include "[[ name|camel_to_snake ]]/_list.html" %}
|
{% include "[[ name|camel_to_snake ]]/_list.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
8
vm_gen/templates/html/search.html
Normal file
8
vm_gen/templates/html/search.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Search results for [[ name|pluralize ]]</h2>
|
||||||
|
<a href="{{ url_for('create_[[ name|camel_to_snake ]]') }}">Create</a>
|
||||||
|
<br>
|
||||||
|
{% include "[[ name|camel_to_snake ]]/_search.html" %}
|
||||||
|
{% endblock %}
|
6
vm_gen/templates/html/update.html
Normal file
6
vm_gen/templates/html/update.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Edit {% include "[[ name|camel_to_snake ]]/_title.html" %}</h2>
|
||||||
|
{% include "[[ name|camel_to_snake ]]/_update.html" %}
|
||||||
|
{% endblock %}
|
@ -1,4 +1,4 @@
|
|||||||
from oshipka.persistance import db, ModelController
|
from oshipka.persistance import db, ModelController, index_service
|
||||||
|
|
||||||
[%- if imports %]
|
[%- if imports %]
|
||||||
[%- for import in imports %]
|
[%- for import in imports %]
|
||||||
@ -10,4 +10,8 @@ from oshipka.persistance import db, ModelController
|
|||||||
[% include "_model_m_n_py" %]
|
[% include "_model_m_n_py" %]
|
||||||
[%- else %]
|
[%- else %]
|
||||||
[% include "_model_py" %]
|
[% include "_model_py" %]
|
||||||
|
[%- endif %]
|
||||||
|
|
||||||
|
[%- if searchable %]
|
||||||
|
index_service.searchables.append([[ name ]])
|
||||||
[%- endif %]
|
[%- endif %]
|
@ -9,39 +9,9 @@ from oshipka.webapp.views import ModelView
|
|||||||
from webapp.models import [[ name ]]
|
from webapp.models import [[ name ]]
|
||||||
from webapp.routes.[[ name|camel_to_snake ]]_hooks import *
|
from webapp.routes.[[ name|camel_to_snake ]]_hooks import *
|
||||||
|
|
||||||
ModelView(app, [[name]]).register_get(
|
ModelView(app, [[name]]).register_get(view_context=get_view_context)
|
||||||
template_func=get_template_func,
|
ModelView(app, [[name]]).register_list(view_context=list_view_context)
|
||||||
template_ctx_func=get_templ_ctx_func,
|
ModelView(app, [[name]]).register_search(view_context=search_view_context)
|
||||||
get_func=get_func,
|
ModelView(app, [[name]]).register_create(view_context=create_view_context)
|
||||||
post_get_func=post_get_func,
|
ModelView(app, [[name]]).register_update(view_context=update_view_context)
|
||||||
)
|
ModelView(app, [[name]]).register_delete(view_context=delete_view_context)
|
||||||
ModelView(app, [[name]]).register_list(
|
|
||||||
template_func=list_template_func,
|
|
||||||
template_ctx_func=list_templ_ctx_func,
|
|
||||||
list_func=list_func,
|
|
||||||
post_list_func=post_list_func,
|
|
||||||
)
|
|
||||||
ModelView(app, [[name]]).register_create(
|
|
||||||
template_func=create_template_func,
|
|
||||||
template_ctx_func=create_templ_ctx_func,
|
|
||||||
args_process_func=create_args_process_func,
|
|
||||||
should_func=create_should_func,
|
|
||||||
post_add=create_post_add_func,
|
|
||||||
post_commit=create_post_commit_func,
|
|
||||||
)
|
|
||||||
ModelView(app, [[name]]).register_update(
|
|
||||||
template_func=update_template_func,
|
|
||||||
template_ctx_func=update_templ_ctx_func,
|
|
||||||
args_process_func=update_args_process_func,
|
|
||||||
should_func=update_should_func,
|
|
||||||
post_add=update_post_add_func,
|
|
||||||
post_commit=update_post_commit_func,
|
|
||||||
)
|
|
||||||
ModelView(app, [[name]]).register_delete(
|
|
||||||
template_func=delete_template_func,
|
|
||||||
template_ctx_func=delete_templ_ctx_func,
|
|
||||||
args_process_func=delete_args_process_func,
|
|
||||||
should_func=delete_should_func,
|
|
||||||
post_add=delete_post_delete_func,
|
|
||||||
post_commit=delete_post_commit_func,
|
|
||||||
)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user