'Flask Jinja2 templating when dealing with one - to- many relationship
so I have created a flask app with three database models one for the users and the other two are parent and child models. The thing is when I am using jinja2 templating the parent table returns on one column none but the other show info. it happens that the last column is related to the child table and is supposed to return info from there. this is the code:
#parent
class Tenant(db.Model):
id = db.Column(db.Integer(), primary_key=True, nullable=False, autoincrement=True, unique=True)
name = db.Column(db.String(length=50), nullable=False)
phone_no = db.Column(db.String(length=50), nullable=False, unique=True)
house_no = db.Column(db.String(length=50), nullable=False, unique=True)
rent = db.relationship('Rent', backref='rent')
def __repr__(self):
return f'Tenant{self.id}'
#child
class Rent(db.Model):
id = db.Column(db.Integer(), primary_key=True, nullable=False, unique=True)
house_no = db.Column(db.String(length=30), nullable=False)
message = db.Column(db.Text(length=256))
payment = db.Column(db.Integer(), nullable=False)
date = db.Column(db.Date, nullable=False)
rent_id = db.Column(db.Integer(), db.ForeignKey('tenant.id'))
def __repr__(self):
return f'Rent{self.id}'
//Rent routes
@app.route('/', methods=['GET', 'POST'])
@login_required
def index():
form = RentForm()
if form.validate_on_submit():
user_create = Rent(house_no=form.house_no.data,
payment=form.payment.data,
message=form.message.data,
date=form.date.data,
)
db.session.add(user_create)
db.session.commit()
return redirect(url_for('rent'))
else:
return render_template('index.html', form=form)
//query- rent
@app.route('/rent_paid', methods=['GET', 'POST'])
@login_required
def rent():
rent = Rent.query.all()
return render_template('rent.html', rent=rent)
//Tenant route
@app.route('/new', methods=['GET', 'POST'])
@login_required
def new():
form = TenantsForm()
if form.validate_on_submit():
user_create = Tenant(name=form.name.data,
phone_no=form.phone_no.data,
house_no=form.house_no.data,
)
db.session.add(user_create)
db.session.commit()
return redirect(url_for('tenants'))
else:
return render_template('tenant.html', form=form)
//query Tenants
@app.route('/tenants', methods=['GET', 'POST'])
@login_required
def tenants():
tenant = Tenant.query.all()
return render_template('table.html', tenant=tenant)
HTML template
<tbody>
{% for tenant in tenant %}
<tr>
<td scope='row'>{{tenant.id}}</td>
<td>{{tenant.name}}</td>
<td>{{tenant.phone_no}}</td>
<td>{{tenant.house_no}}</td>
<td>Ksh {{tenant.rent.}}</td>
so in the HTML template, I want the last column {{ tenant.rent }} to return the actual amount e.g(500USD) but it either returns the rent id or none. how do I code to give the exact amount in the column row.
Solution 1:[1]
Ok so in your model every Tenant can have many Rents. Every Rent has a payment amount associated with it.
When you say you want to show the total amount I am not sure whether you want to show the total payment amount collected from this Tenant up to this point or if just want to show the amount of the last payment the Tenant has made.
You have a lot of options on how to send the information to the template, here I just sent the template a dict where the key is the tenant.id and the value is the total rent up to this point.
@app.route('/tenants', methods=['GET', 'POST'])
@login_required
def tenants():
tenants = Tenant.query.all()
rent = {}
for tenant in tenants:
rents = Tenants.query.filter_by(id=tenant.id).first().rent.all()
total = 0
for rent in rents:
total += rent.payment
rent[tenant.id] = total
return render_template('table.html', tenants=tenants, rent=rent)
And in the template you would do something like this.
{ for tenant in tenants }
<tr>
<td scope='row'>{{ tenant.id }}</td>
<td>{{ tenant.name }}</td>
<td>{{ tenant.phone_no }}</td>
<td>{{ tenant.house_no }}</td>
<td>{{ rent[tenant.id] }}</td>
</tr>
{ endfor }
I am not sure if this is the exact correct syntax since it is hard for me to try it out, but you get the idea. You would also do the same thing if you just want to display the latest payment and not the total, you just need to order the rent by date.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | brudi4550 |