81 lines
2.5 KiB
Python
81 lines
2.5 KiB
Python
from jinja2 import Environment, FileSystemLoader, ChoiceLoader
|
|
from sqlalchemy.orm import class_mapper, RelationshipProperty
|
|
from flask import current_app
|
|
import os
|
|
|
|
def get_env():
|
|
app_loader = current_app.jinja_loader
|
|
|
|
default_path = os.path.join(os.path.dirname(__file__), 'templates')
|
|
fallback_loader = FileSystemLoader(default_path)
|
|
|
|
env = Environment(loader=ChoiceLoader([
|
|
app_loader,
|
|
fallback_loader
|
|
]))
|
|
return env
|
|
|
|
def get_crudkit_template(env, name):
|
|
try:
|
|
return env.get_template(f'crudkit/{name}')
|
|
except Exception:
|
|
return env.get_template(name)
|
|
|
|
def render_field(field, value):
|
|
env = get_env()
|
|
template = get_crudkit_template(env, 'field.html')
|
|
return template.render(
|
|
field_name=field['name'],
|
|
field_label=field.get('label', field['name']),
|
|
value=value,
|
|
field_type=field.get('type', 'text'),
|
|
options=field.get('options', None)
|
|
)
|
|
|
|
def render_table(objects):
|
|
env = get_env()
|
|
template = get_crudkit_template(env, 'table.html')
|
|
return template.render(objects=objects)
|
|
|
|
def render_form(model_cls, values, session=None):
|
|
env = get_env()
|
|
template = get_crudkit_template(env, 'form.html')
|
|
fields = []
|
|
fk_fields = set()
|
|
|
|
mapper = class_mapper(model_cls)
|
|
for prop in mapper.iterate_properties:
|
|
# FK Relationship fields (many-to-one)
|
|
if isinstance(prop, RelationshipProperty) and prop.direction.name == 'MANYTOONE':
|
|
if session is None:
|
|
continue
|
|
|
|
related_model = prop.mapper.class_
|
|
options = session.query(related_model).all()
|
|
fields.append({
|
|
'name': f"{prop.key}_id",
|
|
'label': prop.key,
|
|
'type': 'select',
|
|
'options': [
|
|
{'value': getattr(obj, 'id'), 'label': str(obj)}
|
|
for obj in options
|
|
]
|
|
})
|
|
fk_fields.add(f"{prop.key}_id")
|
|
|
|
# Now add basic columns — excluding FKs already covered
|
|
for col in model_cls.__table__.columns:
|
|
if col.name in fk_fields:
|
|
continue
|
|
if col.name in ('id', 'created_at', 'updated_at'):
|
|
continue
|
|
if col.default or col.server_default or col.onupdate:
|
|
continue
|
|
fields.append({
|
|
'name': col.name,
|
|
'label': col.name,
|
|
'type': 'text',
|
|
})
|
|
|
|
return template.render(fields=fields, values=values, render_field=render_field)
|
|
|