Dropdowns for foreign_keys in fields.
This commit is contained in:
parent
5307210a7b
commit
cfb25f098a
5 changed files with 63 additions and 12 deletions
|
|
@ -1,26 +1,64 @@
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
from sqlalchemy.orm import class_mapper, RelationshipProperty
|
||||||
import os
|
import os
|
||||||
|
|
||||||
FRAGMENT_PATH = os.path.join(os.path.dirname(__file__), 'templates')
|
FRAGMENT_PATH = os.path.join(os.path.dirname(__file__), 'templates')
|
||||||
env = Environment(loader=FileSystemLoader(FRAGMENT_PATH))
|
env = Environment(loader=FileSystemLoader(FRAGMENT_PATH))
|
||||||
|
|
||||||
def render_field(field_name, value):
|
def render_field(field, value):
|
||||||
|
print(field)
|
||||||
template = env.get_template('field.html')
|
template = env.get_template('field.html')
|
||||||
return template.render(field_name=field_name, value=value)
|
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):
|
def render_table(objects):
|
||||||
template = env.get_template('table.html')
|
template = env.get_template('table.html')
|
||||||
return template.render(objects=objects)
|
return template.render(objects=objects)
|
||||||
|
|
||||||
def render_form(model_cls, values):
|
def render_form(model_cls, values, session=None):
|
||||||
template = env.get_template('form.html')
|
template = env.get_template('form.html')
|
||||||
fields = []
|
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:
|
for col in model_cls.__table__.columns:
|
||||||
if col.name == 'id':
|
if col.name in fk_fields:
|
||||||
|
continue
|
||||||
|
if col.name in ('id', 'created_at', 'updated_at'):
|
||||||
continue
|
continue
|
||||||
if col.default or col.server_default or col.onupdate:
|
if col.default or col.server_default or col.onupdate:
|
||||||
continue
|
continue
|
||||||
if col.name in ('created_at', 'updated_at'):
|
fields.append({
|
||||||
continue
|
'name': col.name,
|
||||||
fields.append(col)
|
'label': col.name,
|
||||||
|
'type': 'text',
|
||||||
|
})
|
||||||
|
|
||||||
return template.render(fields=fields, values=values, render_field=render_field)
|
return template.render(fields=fields, values=values, render_field=render_field)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,16 @@
|
||||||
<label>{{ field_name }}</label>
|
<label for="{{ field_name }}">{{ field_label }}</label>
|
||||||
|
|
||||||
|
{% if field_type == 'select' %}
|
||||||
|
<select name="{{ field_name }}" {%- if not options %}disabled{% endif %}>
|
||||||
|
{% if options %}
|
||||||
|
<option value="">-- Select --</option>
|
||||||
|
{% for opt in options %}
|
||||||
|
<option value="{{ opt.value }}" {% if opt.value|string == value|string %}selected{% endif %}>{{ opt.label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<option value="">-- No selection available --</option>
|
||||||
|
{% endif %}
|
||||||
|
</select>
|
||||||
|
{% else %}
|
||||||
<input type="text" name="{{ field_name }}" value="{{ value }}">
|
<input type="text" name="{{ field_name }}" value="{{ value }}">
|
||||||
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% for field in fields %}
|
{% for field in fields %}
|
||||||
{{ render_field(field.name, values.get(field.name, '')) }}
|
{{ render_field(field, values.get(field.name, '')) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<button type="submit">Create</button>
|
<button type="submit">Create</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ def index():
|
||||||
|
|
||||||
devices = device_service.list()
|
devices = device_service.list()
|
||||||
table = render_table(devices)
|
table = render_table(devices)
|
||||||
form = render_form(Device, {})
|
form = render_form(Device, {}, session)
|
||||||
return render_template('index.html', table=table, form=form)
|
return render_template('index.html', table=table, form=form)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
<h1>Devices</h1>
|
<h1>Devices</h1>
|
||||||
{{ table|safe }}
|
{{ table|safe }}
|
||||||
|
|
||||||
<!-- RENDERING FORM START -->
|
|
||||||
<h2>Add Device</h2>
|
<h2>Add Device</h2>
|
||||||
{{ form|safe }}
|
{{ form|safe }}
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue