I'm making a really basic website where users essentially just submit data into some forms and they will be able to review their data in another page. I feel like I'm going to be repeating myself far too much.
This is how I'm planning to display the users records, the trouble I'm having is I have about six more tables of data that is slightly different. So I can't just hard-code a template because the number of columns and the names of the columns is slightly different in each table. I know I could just make six different HTML files but that just seems silly. I feel like I need to somehow loop over the attributes of the models and then somehow display them in the template?
Is there a better way of displaying database data in a template?
class (db.Model):
__abstract__ = True
employee_name = db.Column(db.String(50), nullable=False)
date_submitted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
comment = db.Column(db.String(100), nullable=True)
class FridgeFreezerTempTable(Base):
id = db.Column(db.Integer, primary_key=True)
unit_name = db.Column(db.String(50), nullable=False)
unit_type = db.Column(db.String(50), nullable=False)
temperature = db.Column(db.String(10), nullable=False)
company_id = db.Column(db.Integer, db.ForeignKey('user.id'),nullable=False)
@app.route("/unit_temp_records/<int:page_number>")
def unit_records(page_number):
"""
records = pagiantion object
page number = the current page
"""
records = FridgeFreezerTempTable.query.filter_by(user=current_user).paginate(per_page=5,
page=page_number, error_out=True)
return render_template("unit_temp_records.html", user_records=records, table=table)
{% extends "records.html"%}
<!--This is garbage, find a way to make all below a template.. dir? __dict__???-->
{%block recordcontent%}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Unit Name</th>
<th scope="col">Unit Type</th>
<th scope="col">Temperature</th>
<th scope="col">Employee Name</th>
<th scope="col">Comment</th>
<th scope="col">Date Submitted</th>
</tr>
</thead>
<tbody>
{% for record in user_records.items %}
<tr>
<th scope="col">{{ loop.index }}</th>
<td>{{record.unit_name}}</td>
<td>{{record.unit_type}}</td>
<td>{{record.temperature}}</td>
<td>{{record.employee_name}}</td>
<td>{{record.comment}}</th>
<td>{{record.date_submitted}}</td>
</tr>
{% endfor %}
</tbody>
<!-- Also garbage (maybe figure out how to put this into records template -->
{% for page in user_records.iter_pages() %}
{% if page %}
<a class="test" href="{{url_for('unit_records', page_number=page) }}">{{ page }}</a>
{% else %}
.
{% endif %}
{% endfor %}
</table>
{% endblock%}
```
-
5\$\begingroup\$ The site standard is for the title to simply state the task accomplished by the code, not your concerns about it. Please see How do I ask a good question? for examples, and revise the title accordingly. \$\endgroup\$Martin R– Martin R2019年12月20日 19:21:52 +00:00Commented Dec 20, 2019 at 19:21
1 Answer 1
Perhaps the templates can be generated by a function. Pass in a list of the attribute names, and it returns a template string. Or pass in the table name, and query the column names to make the template. Then use render_template_string()
instead of render_template()
.
This code is rough and untested, but outlines what I'm thinking:
def column_headers(attrs):
headers = (f'<th scope="col">{attr.replace("_"," ").titlecase()}</th>'
for attr in attrs)
return '\n'.join(headers)
def columns(attrs):
column_refs = (f'<td>{{record.{attr}}}</td>' for attr in attrs)
return '\n'.join(column_refs)
def make_template(attrs):
template_string = ["""
{% extends "records.html"%}
{%block recordcontent%}
<table class="table table-striped">
<thead>
<tr>
""",
column_headers(attrs),
"""
</thead>
<tbody>
{% for record in user_records.items %}
<tr>
<th scope="col">{{ loop.index }}</th>
""",
columns(attrs),
"""
</tr>
{% endfor %}
</tbody>
</table>
{% endblock%}
"""]
return '\n'.join(template_string)
FridgeFreezerTemplate = make_template("""
unit_type
temperature
employee_name
comment
date_submitted
""".strip().split())
@app.route("/unit_temp_records/<int:page_number>")
def unit_records(page_number):
"""
records = pagiantion object
page number = the current page
"""
records = FridgeFreezerTempTable.query.filter_by(user=current_user).paginate(per_page=5,
page=page_number, error_out=True)
return render_template_string(FridgeFreezerTemplate, user_records=records, table=table)