How to properly unpack a nested dictionary in a django HTML template? - python

So I was able to figure out how to unpack a dictionary keys and values on to a HTML template, but I am a bit confused as to how to unpack if if a dictionary value is a QuerySet. For example I passing in all the timeslots of the given user into the dictonary. How can I unpack the attributes of the TimeSlot QuerySet for each timeslot such as the start time and end time?
This is my HTML Template:
<table>
{% for key, value in user_info.items %}
{% for key2,value2 in value.items %}
<tr>
<td>{{key2}}</td>
<td>{{value2}}<td>
</tr>
{% endfor %}
<br>
{% endfor %}
</table>
My function in views.py
def check_food_availibility(request):
food = FoodAvail.objects.all()
timeslots = TimeSlot.objects.all()
users_dict = {}
for i in range(len(user_info)):
user = {
"author": None,
"food_available": None,
"description": None,
"timeslot": None
}
user["author"] = user_info[i].author.username
user["food_available"] = user_info[i].food_available
user["description"] = user_info[i].description
if TimeSlot.objects.filter(time_slot_owner=user_info[i].author):
user["timeslot"] = TimeSlot.objects.filter(time_slot_owner=user_info[i].author)
users_dict[user_info[i].author.username] = user
return render(request, "food_avail/view_food_avail.html", {"user_info": users_dict})
This is how it shows up currently:

try this
<table>
{% for key, value in user_info.items %}
{% for key2,value2 in value.items %}
<tr>
<td>{{key2}}</td>
{% if key2 == 'timeslot' %}
<td>
{% for i in value2 %}
i.start_time <-> i.end_time // just an example put your field here
{% endfor %}
</td>
{% else %}
<td>{{value2}}<td>
{% endif %}
</tr>
{% endfor %}
<br>
{% endfor %}
</table>

Related

Flask list of fields gets the data inside just the first element

I am trying to get the data from a form that is made dynamically using Flask and WTForms. To do that I've created a list that gets populated when a user opens the link, but when I try to get the data from html I only get the data from the first element of the list.
Forms:
class Details_Form(FlaskForm):
preschool_groups = []
classes = []
continue_button = SubmitField('Continuă')
def appeend_group(self):
preschool_details = Preschool_Details()
self.preschool_groups.append(preschool_details)
def appeend_class(self, choices):
class_details = Classes_Details()
class_details.class_type.choices = choices
self.classes.append(class_details)
class Preschool_Details(FlaskForm):
group_name = StringField('', validators=[DataRequired()])
group_size = IntegerField('', validators=[DataRequired()])
class Classes_Details(FlaskForm):
class_name = StringField('', validators=[DataRequired()])
class_size = IntegerField('', validators=[DataRequired()])
class_type = SelectField('', validators=[DataRequired()])
Routes:
#app.route('/detalii-scoala/<school>/<groups>/<classes>', methods=['GET','POST'])
#login_required
def school_details_page(school, groups, classes):
groups = int(groups)
classes = int(classes)
details_form = Details_Form()
details_form.classes.clear()
details_form.preschool_groups.clear()
school_db_item = db.session.query(School).join(User, User.id == School.psychologist_id).filter(User.id == current_user.id).filter(School.school==school).first()
education_types = school_db_item.education_type.split(',')
for _ in range(groups):
details_form.appeend_group()
for _ in range(classes):
details_form.appeend_class(education_types)
if details_form.continue_button.data and details_form.validate_on_submit():
for preschool_details in details_form.preschool_groups:
group = Group(name=preschool_details.group_name.data, number_of_pupils=preschool_details.group_size.data, school_id=school_db_item.id)
db.session.add(group)
for class_details in details_form.classes:
print(class_details.class_name.data)
c = Classes(name=class_details.class_name.data, number_of_students=class_details.class_size.data, class_type=class_details.class_type.data, school_id=school_db_item.id)
db.session.add(c)
db.session.commit()
details_form.classes.clear()
details_form.preschool_groups.clear()
flash('Detaliile au fost inregistrate')
return redirect(url_for('session_page'))
return render_template('detalii-scoala.html', details_form=details_form)
html:
<form action="" method="post">
{{ details_form.hidden_tag() }}
<table>
{% for preschool in details_form.preschool_groups %}
<tr>
<td><p>
{{ preschool.group_name(class_="form-control") }}<br>
{% for error in preschool.group_name.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ preschool.group_size(class_="form-control") }}<br>
{% for error in preschool.group_size.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
</tr>
{% endfor %}
</table>
<br>
<table>
<tr>
<td>Denumire clasă</td>
<td>Nr. elevi înscrişi</td>
<td>Ciclul</td>
</tr>
{% for class in details_form.classes %}
<tr>
<td><p>
{{ class.class_name(class_="form-control") }}<br>
{% for error in class.class_name.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ class.class_size(class_="form-control") }}<br>
{% for error in class.class_size.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ class.class_type(class_="form-control") }}<br>
{% for error in class.class_type.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
</tr>
{% endfor %}
</table>
<p>{{ details_form.continue_button(class_="btn btn-primary") }}</p>
</form>
Front end works, the only problem is when I try to add the data from thee form in the database.
The problem was that HTML fields were having the same name. To solve that I used request.form.getlist('name) to create the lists

How do you add a summary row for Flask-Admin?

In my flask-admin index_view, I am displaying financial information for my rows.
I would like to add an extra row, "summary row", at the bottom of my index_view table which sums up all the columns.
How can I accomplish this?
There's a couple of things you need to do. Provide a custom list.html template and override the render() method for the view. In the render method inject your summary data into the kwargs and in the custom template use the summary data to output appropriate html. You could add the summary data to the end of the existing data table or add it to a separate table, as seen in the example below.
Here's a self-contained example (two files) using Flask-Admin 1.5, SQLAlchemy and SQLite. custom_list.html is taken directly from flask-admin list.html and we are manipulating the block beginning at line 68:
{% block model_list_table %}
...
{% endblock %}
Note that in the render() method the summary data is an array of dicts. Each dict has a 'title' attribute (e.g 'title: 'Page Total' plus an attribute for each of the columns summary data is required.
app.py
import random
import string
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib.sqla import ModelView
from flask_admin import Admin, expose
# Create application
from sqlalchemy import func
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
db = SQLAlchemy(app)
# Flask views
#app.route('/')
def index():
return 'Click me to get to Admin!'
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False, unique=True)
cost = db.Column(db.Integer(), nullable=False)
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return "Name: {name}; Cost : {cost}".format(name=self.name, cost=self.cost)
class ProjectView(ModelView):
# don't call the custom page list.html as you'll get a recursive call
list_template = 'admin/model/custom_list.html'
form_columns = ('name', 'cost')
page_size = 5
def page_cost(self, current_page):
# this should take into account any filters/search inplace
_query = self.session.query(Project).limit(self.page_size).offset(current_page * self.page_size)
return sum([p.cost for p in _query])
def total_cost(self):
# this should take into account any filters/search inplace
return self.session.query(func.sum(Project.cost)).scalar()
def render(self, template, **kwargs):
# we are only interested in the list page
if template == 'admin/model/custom_list.html':
# append a summary_data dictionary into kwargs
_current_page = kwargs['page']
kwargs['summary_data'] = [
{'title': 'Page Total', 'name': None, 'cost': self.page_cost(_current_page)},
{'title': 'Grand Total', 'name': None, 'cost': self.total_cost()},
]
return super(ProjectView, self).render(template, **kwargs)
admin = Admin(app, template_mode="bootstrap3")
admin.add_view(ProjectView(Project, db.session))
def build_sample_db():
db.drop_all()
db.create_all()
for _ in range(0, 100):
_cost = random.randrange(1, 1000)
_project = Project(
name=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)),
cost=_cost
)
db.session.add(_project)
db.session.commit()
if __name__ == '__main__':
build_sample_db()
app.run(port=5000, debug=True)
templates/admin/model/custom_list.html
{% extends 'admin/model/list.html' %}
{% block model_list_table %}
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover model-list">
<thead>
<tr>
{% block list_header scoped %}
{% if actions %}
<th class="list-checkbox-column">
<input type="checkbox" name="rowtoggle" class="action-rowtoggle" title="{{ _gettext('Select all records') }}" />
</th>
{% endif %}
{% block list_row_actions_header %}
{% if admin_view.column_display_actions %}
<th class="col-md-1"> </th>
{% endif %}
{% endblock %}
{% for c, name in list_columns %}
{% set column = loop.index0 %}
<th class="column-header col-{{c}}">
{% if admin_view.is_sortable(c) %}
{% if sort_column == column %}
<a href="{{ sort_url(column, True) }}" title="{{ _gettext('Sort by %(name)s', name=name) }}">
{{ name }}
{% if sort_desc %}
<span class="fa fa-chevron-up glyphicon glyphicon-chevron-up"></span>
{% else %}
<span class="fa fa-chevron-down glyphicon glyphicon-chevron-down"></span>
{% endif %}
</a>
{% else %}
{{ name }}
{% endif %}
{% else %}
{{ name }}
{% endif %}
{% if admin_view.column_descriptions.get(c) %}
<a class="fa fa-question-circle glyphicon glyphicon-question-sign"
title="{{ admin_view.column_descriptions[c] }}"
href="javascript:void(0)" data-role="tooltip"
></a>
{% endif %}
</th>
{% endfor %}
{% endblock %}
</tr>
</thead>
{% for row in data %}
<tr>
{% block list_row scoped %}
{% if actions %}
<td>
<input type="checkbox" name="rowid" class="action-checkbox" value="{{ get_pk_value(row) }}" title="{{ _gettext('Select record') }}" />
</td>
{% endif %}
{% block list_row_actions_column scoped %}
{% if admin_view.column_display_actions %}
<td class="list-buttons-column">
{% block list_row_actions scoped %}
{% for action in list_row_actions %}
{{ action.render_ctx(get_pk_value(row), row) }}
{% endfor %}
{% endblock %}
</td>
{%- endif -%}
{% endblock %}
{% for c, name in list_columns %}
<td class="col-{{c}}">
{% if admin_view.is_editable(c) %}
{% set form = list_forms[get_pk_value(row)] %}
{% if form.csrf_token %}
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }}
{% else %}
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }}
{% endif %}
{% else %}
{{ get_value(row, c) }}
{% endif %}
</td>
{% endfor %}
{% endblock %}
</tr>
{% else %}
<tr>
<td colspan="999">
{% block empty_list_message %}
<div class="text-center">
{{ admin_view.get_empty_list_message() }}
</div>
{% endblock %}
</td>
</tr>
{% endfor %}
</table>
</div>
<h3>Summaries</h3>
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover model-list">
<thead>
<tr>
{% if actions %}
<th class="list-checkbox-column">
</th>
{% endif %}
<th class="col-md-1"></th>
{% for c, name in list_columns %}
{% set column = loop.index0 %}
<th class="column-header col-{{c}}">
{{ name }}
</th>
{% endfor %}
</tr>
</thead>
{% for row in summary_data %}
<tr>
<td colspan="2"><strong>{{ row['title'] or ''}}</strong></td>
{% for c, name in list_columns %}
<td class="col-{{c}}">
{{ row[c] or ''}}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
{% else %}
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
{% endif %}
{% endblock %}
{% endblock %}

Django/Python : Sort python's dictionaries with the equals key

I am currently trying to sort two Python dictionaries into an HTML array such as:
#Headers
DictA = {'value': 'valeur', 'name': 'nom' }
#Data
DictB = {'value': '456', 'name': 'Test' }
I wanted to sort these two dictionaries in order to get the '456' in DictB equals to the key 'value' in DictA.
Note: I used other dictionaries than DictA and DictB, it was just an example. But it fits my problem.
In my views.py, I define my two dictionaries such as:
headers = json.loads(entries[0].form_data_headers)
data = json.loads(entries[1].saved_data)
valuesData = data.values()
then I pass them into the template.html via the context:
context = {'entries': entries, 'form_entry_id': form_entry_id, 'headers': headers, 'data': data, 'valuesData': valuesData}
Thus, in my template, it will print an array with the headers (DictA) and the datas (DictB).
In my template I make this code:
<thead>
<!-- Test pr voir si les values sont pris en compte ou non -->
<p>{{valuesData}}</p>
<tr>
{% for entry in headers %}
<td>
{{ entry }}
</td>
{% endfor %}
</tr>
</thead>
And the datas are in another for loop:
<tbody>
<thead>
<!-- Test pr voir si les values sont pris en compte ou non -->
<p>{{valuesData}}</p>
<tr>
{% for entry in dataValues %}
<td>
{{ entry }}
</td>
{% endfor %}
</tr>
</thead>
</tbody>
The result is kinda such as follow:
name equals 456 (instead of the name of the form)
geom equals test (instead of my coordinate)
etc.
It doesn't match the right header.
I was thinking about making two for loops with an if statement in it:
{%if headers['name'] == dataValues['name']%}
<td>dataValues['name']</td>
But I get an error as dataValues['name'] could not be parsed.
The rest of the code is in Javascript:
{% endblock content %}
{% block javascript %}
<script type="text/javascript">
function GetURLParameter(param_name){
var sPageURL = window.location.search.substring(1);
var sParameterName = sPageURL.split('=');
return sParameterName[1];
}
var name= GetURLParameter(name);
document.querySelector('.page-header .value').innerHTML = name;
</script>
{% endblock %}
{% block main-content-inner-attrs %}
{% endblock main-content-inner-attrs %}
{% block sidebar-wrapper %}
{% endblock sidebar-wrapper %}
The rest of the code is in javascript :
{% endblock content %}
{% block javascript %}
<script type="text/javascript">
function GetURLParameter(param_name){
var sPageURL = window.location.search.substring(1);
var sParameterName = sPageURL.split('=');
return sParameterName[1];
}
var name= GetURLParameter(name);
document.querySelector('.page-header .value').innerHTML = name;
</script>
{% endblock %}
{% block main-content-inner-attrs %}
{% endblock main-content-inner-attrs %}
{% block sidebar-wrapper %}
{% endblock sidebar-wrapper %}
Here is the right answer :
<tr>
{% for cle, valeur in headersLoop %}
{% for cleVD, valeurVD in valuesData %}
{% if cle == cleVD %}
<td>
<p> {{cle}}{{valeurVD}} </p>
</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
I marked it as solved. And create a new topic. Thanks all.

django sort dict after query

have a table with websites and a many to one table with descriptions
trying to get a list, firstly getting the latest descriptions and then displaying them ordered by the content of the descriptions...
have the following in views.py
def category(request, category_name_slug):
"""Category Page"""
context_dict = {}
try:
category = Category.objects.get(slug=category_name_slug)
subcategory = SubCategory.objects.filter(category=category)
websites = Website.objects.filter(sub_categories=subcategory, online=True, banned=False)
sites = websites
descriptions = WebsiteDescription.objects.prefetch_related("about")
descriptions = descriptions.filter(about__in=sites)
descriptions = descriptions.order_by('about', '-updated')
descs = []
last_site = "" # The latest site selected
# Select the first (the latest) from each site group
for desc in descriptions:
if last_site != desc.about.id:
last_site = desc.about.id
desc.url = desc.about.url
desc.hs_id = desc.about.id
desc.banned = desc.about.banned
desc.referral = desc.about.referral
descs.append(desc)
context_dict['descs'] = descs
context_dict['websites'] = websites
context_dict['subcategory'] = subcategory
context_dict['category'] = category
except SubCategory.DoesNotExist:
pass
return render(request, 'category.html', context_dict)
this gives me a list with sites and their latest descriptions, so i have the following in category.html
{% if category %}
<h1>{{ category.name }}</h1>
{% for subcategory in category.subcategory_set.all %}
{{ subcategory.name }} ({{ subcategory.website_set.all|length }})
{% endfor %}
{% if descs %}
{% load endless %}
{% paginate descs %}
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo" %}
<ul id='list' class='linksteps'>
<a href="/{{ desc.about_id }}" rel="nofollow" target="_blank">
<img src="/static/screenshots/{{ desc.about_id }}.png" />
</a>
<li><h3>{{ desc.about_id }}{% if desc.title %} - {{ desc.title }} {% endif %}</h3>
{% if desc.description %}<b>Description: </b>{{ desc.description }}
<br />{% endif %} {% if desc.subject %}<b>Keywords: </b>{{ desc.subject }}
<br />{% endif %} {% if desc.type %}<b>Type: </b>{{ desc.type }}
<br />{% endif %} {% if desc.officialInfo %} {% if desc.language %}<b>Language: </b>{{ desc.language }}
<br />{% endif %} {% if desc.contactInformation %}<b>Contact info: </b>{{ desc.contactInformation }}
<br />{% endif %}
{% else %}
{% endif %}
</li>
</ul>
</div>
{% endfor %}
{% show_pages %}
{% else %}
<strong>No websites currently in category.</strong>
{% endif %}
{% else %}
The specified subcategory {{ category_name }} does not exist!
{% endif %}
Initially i used dictsort
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo"|dictsortreversed:"referral" %}
to give me the list in the desired order, so i was all happy ;)
Then however i decided i needed some pagination because the lists became too long.
django-endless-pagination works fine and does what its supposed too, however it splits up my list before the dictsort kicks in.
is there a way to sort before pagination happens and after i ordered_by at the initial query to have the latest descriptions selected?
much obliged
EDIT:
not getting any answers so my question might not be clear.
as far as i understand i need to sort the values in context_dict at the end in views.py replacing the dictsort as in the template
SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1
SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1

How to iterate through a list of dictionaries in Jinja template?

I tried:
list1 = [{"username": "abhi", "pass": 2087}]
return render_template("file_output.html", list1=list1)
In the template:
<table border=2>
<tr>
<td>
Key
</td>
<td>
Value
</td>
</tr>
{% for dictionary in list1 %}
{% for key in dictionary %}
<tr>
<td>
<h3>{{ key }}</h3>
</td>
<td>
<h3>{{ dictionary[key] }}</h3>
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
The above code is splitting each element into multiple characters:
[
{
"
u
s
e
r
...
I tested the above nested loop in a simple Python script and it works fine but not in Jinja template.
Data:
parent_list = [{'A': 'val1', 'B': 'val2'}, {'C': 'val3', 'D': 'val4'}]
in Jinja2 iteration:
{% for dict_item in parent_list %}
{% for key, value in dict_item.items() %}
<h1>Key: {{key}}</h1>
<h2>Value: {{value}}</h2>
{% endfor %}
{% endfor %}
Note:
Make sure you have the list of dict items. If you get UnicodeError may be the value inside the dict contains unicode format. That issue can be solved in your views.py.
If the dict is unicode object, you have to encode into utf-8.
As a sidenote to #Navaneethan 's answer, Jinja2 is able to do "regular" item selections for the list and the dictionary, given we know the key of the dictionary, or the locations of items in the list.
Data:
parent_dict = [{'A':'val1','B':'val2', 'content': [["1.1", "2.2"]]},{'A':'val3','B':'val4', 'content': [["3.3", "4.4"]]}]
in Jinja2 iteration:
{% for dict_item in parent_dict %}
This example has {{dict_item['A']}} and {{dict_item['B']}}:
with the content --
{% for item in dict_item['content'] %}{{item[0]}} and {{item[1]}}{% endfor %}.
{% endfor %}
The rendered output:
This example has val1 and val2:
with the content --
1.1 and 2.2.
This example has val3 and val4:
with the content --
3.3 and 4.4.
{% for i in yourlist %}
{% for k,v in i.items() %}
{# do what you want here #}
{% endfor %}
{% endfor %}
Just a side note for similar problem (If we don't want to loop through):
How to lookup a dictionary using a variable key within Jinja template?
Here is an example:
{% set key = target_db.Schema.upper()+"__"+target_db.TableName.upper() %}
{{ dict_containing_df.get(key).to_html() | safe }}
It might be obvious. But we don't need curly braces within curly braces. Straight python syntax works. (I am posting because I was confusing to me...)
Alternatively, you can simply do
{{dict[target_db.Schema.upper()+"__"+target_db.TableName.upper()]).to_html() | safe }}
But it will spit an error when no key is found. So better to use get in Jinja.
**get id from dic value. I got the result.try the below code**
get_abstracts = s.get_abstracts(session_id)
sessions = get_abstracts['sessions']
abs = {}
for a in get_abstracts['abstracts']:
a_session_id = a['session_id']
abs.setdefault(a_session_id,[]).append(a)
authors = {}
# print('authors')
# print(get_abstracts['authors'])
for au in get_abstracts['authors']:
# print(au)
au_abs_id = au['abs_id']
authors.setdefault(au_abs_id,[]).append(au)
**In jinja template**
{% for s in sessions %}
<h4><u>Session : {{ s.session_title}} - Hall : {{ s.session_hall}}</u></h4>
{% for a in abs[s.session_id] %}
<hr>
<p><b>Chief Author :</b> Dr. {{ a.full_name }}</p>
{% for au in authors[a.abs_id] %}
<p><b> {{ au.role }} :</b> Dr.{{ au.full_name }}</p>
{% endfor %}
{% endfor %}
{% endfor %}

Categories

Resources