Dropdowns for foreign_keys in fields.

This commit is contained in:
Yaro Kasear 2025-09-02 14:05:52 -05:00
parent 5307210a7b
commit cfb25f098a
5 changed files with 63 additions and 12 deletions

View file

@ -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)

View file

@ -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 %}

View file

@ -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>

View file

@ -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__':

View file

@ -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>