I am running a db query with sqlalchemy and then pushing this output into an HTML page with flask and python. However, the output is formatted as a list, and I am trying to remove the quotes around it and format it nicer.
# views.py
#buyers_blueprint.route('/welcome')
#login_required
def welcome_user():
user = current_user
events = db.session.query(Events.eventname)
return render_template('welcome.html', user=user, events=events)
The welcome.html page is simple and looks like this
welcome.html
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Events Dashboard</h1>
<p>{{user}}! You are logged in.<br>
Here is a list of your events</p><br>
<p>
{% for event in events %}
<li>{{event}}</li>
{% endfor %}
</p>
</div>
{% endblock %}
The output looks like this.
('Event 1',)
('Event 2',)
How do I remove the quotes, and comma to format it so it looks nicer? Thank you so much.
So, thanks to help from others, I came up with an answer. In the HTML, I just needed to ask for the first in tuple.
welcome.html
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Events Dashboard</h1>
<p>{{user}}! You are logged in.<br>
Here is a list of your events</p><br>
<p>
{% for event in events %}
<li>{{event[0]}}</li>
{% endfor %}
</p>
</div>
{% endblock %}
Related
I am a little confused about what {% extends base %} is extending at the start of index.html in Bokeh server application packages.
Examples of this can be seen in:
Bokeh Docs: Embedding in Templates
{% extends base %}
{% block contents %}
<div>
<p> Hello {{ user_id }}, AKA '{{ last_name }}, {{ first_name }}'! </p>
</div>
{% endblock %}
Bokeh Server Application Examples
Example code from the Gapminder package in templates/index.html
{% extends base %}
{% block title %}Bokeh Gapminder Example{% endblock %}
{% block postamble %}
<style>
{% include 'styles.css' %}
</style>
{% endblock %}
What is this "base" that is being extended?
I see that there is a "contents" block, "title" block, and "postamble" block from the above examples.
How do I know what other jinja blocks I can modify?
Thanks.
I am using Flask and I am looping through a table Buyers object in Jinja. What I want to happen is to show a message in the HTML page if there is no data in a specific field Buyers.supplier of the table.
Let's say the table has 5 entries and there are no fields present, what happens in my present code is that I see my message 5 times.
Is there a way to just show the HTML message if all of the fields are empty? Thank you!
main.html
<div class="card-deck">
{# Go through each blog post #}
{% for sched in buyer_sched|sort(attribute='time') %}
{# Only show if a supplier has been matched#}
{% if sched.supplier.company %}
<div class="row pl-3 ml-1">
<p>Show some information</p>
</div>
{% else %}
<p>There is no data</p>
{% endif %}
{% endfor %}
<div />
{% else %}
<p>Please login and register</p>
{% endif %}
{% endblock %}
I answered this in a different (perhaps not so pythonic way).
I basically iterated through the field on the python side and used a counter to count up. If the number was greater than 0, then when I passed the integer into my html template, it wouldn't show the message.
Thank you!
buyer_sched = db.session.query(Buyerschedule).\
filter(Buyerschedule.buyer_id == buyer_id).all()
# Iterate through schedule and if all are none, set
# completed to none
completed = 0
for sched in buyer_sched:
print(f'The schedule name is: {sched.id}')
if sched.supplier_id:
completed = completed + 1
print(f'completed is {completed}')
print(f'completed is equal to {completed}')
You could create a custom jinja filter (https://flask.palletsprojects.com/en/1.1.x/templating/#registering-filters) to check if all are empty before the for loop:
def all_empty(data, key):
return all(not d[key] for d in data)
app.jinja_env.filters['all_empty'] = all_empty
Once registered, you can call that function in your template:
<div class="card-deck" >
{% if data|all_empty('supplier') %}
<p>There is no data</p>
{% else %}
{% for sched in data %}
{% if sched.supplier and sched.supplier.company %}
<div class="row pl-3 ml-1">
<p>{{ sched.supplier.company }}</p>
</div>
{% endif %}
{% endfor %}
{% endif %}
</div>
I'm trying to get data on_submit from input fields in multiple form fields. But I want to use one submit button from one of the fields. is this even possible?
class Form1(FlaskForm):
entry1 = StringField(('Entry 1'))
class Form2(FlaskForm):
entry2 = StringField(('Entry 2'))
submit = SubmitField(('Register'))
#app.route('/index', methods=['GET', 'POST'])
def index():
form1= Form1()
form2= Form2()
if form2.validate_on_submit():
entry1 = request.form.get('entry1')
entry2= request.form.get('entry2')
flash((entry1))
flash((entry2))
return redirect(url_for('main.index'))
return render_template('index.html', form1=form1, form2=form2)
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form1)}}
{{ wtf.quick_form(form2) }}
</div>
</div>
{% endblock %}
You could move the Submit button to a new class that inherits the other forms. From what I understand, validate_on_submit() processes and validates the fields of the called form, which includes any fields of inherited form classes.
class Form1(FlaskForm):
entry1 = StringField(('Entry 1'))
class Form2(FlaskForm):
entry2 = StringField(('Entry 2'))
class FinalForm(Form1, Form2):
submit = SubmitField(('Register'))
Now you only have to refer to the final form in the call and rendering.
#app.route('/', methods=['GET', 'POST'])
def index():
form = FinalForm()
if form.validate_on_submit():
entry1 = request.form.get('entry1')
entry2 = request.form.get('entry2')
flash((entry1))
flash((entry2))
return redirect(url_for('index'))
return render_template('index.html', form=form)
Here were the basic html templates I tested with success, trying to keep with the format you showed.
base.html :
{% extends 'bootstrap/base.html' %}
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block app_content %}{% endblock %}
</div>
{% endblock %}
index.html :
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}
I am not entirely sure if I understand your problem correctly, but you can use WTForms to build your forms. You'd have to define another class though that holds the both classes with the fields you need to submit.
https://wtforms.readthedocs.io/en/stable/
I have this code(which doesn't give me expected result)
#subject_content.html
{% block main-menu %}
{% include "subject_base.html" %}
{% endblock %}
#subject_base.html
....
....
<div id="homework" class="tab-section">
<h2>Homework</h2>
{% include "subject_file_upload.html" %}
</div>
child template:
#subject_file_upload.html
<form action="." method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit">
</form>
and my view
#views.py
#login_required
def subject(request,username, subject):
if request.method == "POST":
form = CarsForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("/")
form = CarsForm()
return render_to_response('subject_content.html', {'form':form}, context_instance=RequestContext(request))
The above code creates HTML in the way I want it to be, however the form does not update database.
BUT,
If I skip the middle template and go directly to the uploading form, it works fine:
#subject_content.html
{% block main-menu %}
{% include "subject_file_upload.html" %}
{% endblock %}
Help me please to make it work with middle template.
I want to do this, because I don't wan't to type the same code more than once.
Like #Besnik suggested, it's pretty simple:
{% include "subject_file_upload.html" with form=form foo=bar %}
The documentation for include mentions this. It also mentions that you can use only to render the template with the given variables only, without inheriting any other variables.
Thank you #Besnik
I need to check if the variable texts is defined or not in index.html.
If the variable is defined and not empty then I should render the loop. Otherwise, I want to show the error message {{error}}.
Basically this in PHP
if (isset($texts) && !empty($texts)) {
for () { ... }
}
else {
print $error;
}
index.html
{% for text in texts %}
<div>{{error}}</div>
<div class="post">
<div class="post-title">{{text.subject}}</div>
<pre class="post-content">{{text.content}}</pre>
</div>
{% endfor %}
How do I say this in jinja2?
I think your best bet is a combination of defined() check along with looking at the length of the array via length() function:
{% if texts is defined and texts|length > 0 %}
...
{% endif %}
To test for presence ("defined-ness"?), use is defined.
To test that a present list is not empty, use the list itself as the condition.
While it doesn't seem to apply to your example, this form of the emptiness check is useful if you need something other than a loop.
An artificial example might be
{% if (texts is defined) and texts %}
The first text is {{ texts[0] }}
{% else %}
Error!
{% endif %}
Take a look at the documentation of Jinja2 defined(): http://jinja.pocoo.org/docs/templates/#defined
{% if variable is defined %}
value of variable: {{ variable }}
{% else %}
variable is not defined
{% endif %}
Is it clear enough? In your case it could look like this:
{% if texts is defined %}
{% for text in texts %}
<div>{{ error }}</div>
<div class="post">
<div class="post-title">{{ text.subject }}</div>
<pre class="post-content">{{ text.content }}</pre>
</div>
{% endfor %}
{% else %}
Error!
{% endif %}
As mentioned in the documentation, you could also write:
{% for text in texts %}
<div class="post">
<div class="post-title">{{text.subject}}</div>
<pre class="post-content">{{text.content}}</pre>
</div>
{% else %}
<div>{{ error }}</div>
{% endfor %}
It handles both the case where texts is undefined, and the case where texts is empty.
This is a neat and simple solution that worked well for me!
{% if texts is defined and texts[0] is defined %}
...
{% endif %}
It's possible that texts could be defined but contain a single list element which is an empty string; For example:
texts = ['']
In this case, testing if texts is defined will produce a true result so you should test the first element instead:
{% if texts[0] != '' %}
..code here..
{% endif %}
You might also want to combine that with the |length filter to make sure it only has one element.
This worked for me when working with the UPS API where if there is only one object in a parent object the child is just an object, but when there is more than one child it's a array of objects.
{% if texts[0] %}
..code here..
{% endif %}
This is what worked for my use case in my Django app:
I needed to pass a queryset as context to an html template and display the block only if the queryset had values
Queryset:
events = Event.objects.filter(schedule_end__gte=date.today()).order_by('-created_at')
Passed context dictionary as follows:
{ "events" : events }
HTML template
{% if events %}
<h3>Upcoming Events</h3>
<ul>
{% for event in events %}
<li><h4>{{ event.title }}</h4></li>
{% endfor %}
</ul>
{% endif %}
This works for me ( But I make sure to return an empty array [] and not None if its empty )
{% if array %}
<table class="table">
...
</table>
{% endif %}
We can check if array is not empty by writing below jinja code.
where the content2 is an array defined under py file. #app.route("/<name>") def home(name): return render_template("index.html", content=name, content2=[])
{% if content2 %}
<div>
<h2>Array elements are available</h2>
{% for con2 in content2 %}
<p> {{con2}} </p>
{% endfor %}
</div>
{% endif %}
Thanks