looping thru a python list and display results in flask - python

python function returns a python list
python module function
with open(xml_append_back) as fd1:
doc = xmltodict.parse(fd1.read())
codes = []
for p in doc['Des']['Config']:
codes.append(p['#Id'])
codes.append(pl['#name'])
print(codes)
return codes
codes = ['f2ee4681', 'Conf. no: 1', '89282c5b', 'Conf. no: 2', '3e9dd219', 'Conf. no: 3', '773044b9'] # returned from python to flask template result.html
I call this variable in my templates/flask.html like this
flask file
#app.route('/result',methods = ['POST', 'GET'])
def result():
const_ids=run_d.run_de_selected_configs() # this function returns "codes"
return render_template("result.html",result =
constraint_names_from_form,result1=constraint_ids)
result.html file
{% for key,key1 in result1 %}
<tr class="even"><td>{{ key }}</td><td>{{ key1 }}</td></tr>
should be
<tr class="even"><td>f2ee4681</td><td>Conf. no: 1</td></tr>
{% endfor %}
What am I doing wrong

To answer my own question
I used zip utility in my python code as zip is not available in flask
function returncodes()
-------
---------
return zip(codes,codeNames) # in my case
no change in the flask template
#app.route('/result',methods = ['POST', 'GET'])
def result():
const_ids=run_d.run_de_selected_configs() # this function returns "codes"
return render_template("result.html",result =
constraint_names_from_form,result1=constraint_ids)
now in my result.html
{% for keys,keys2 in result1 %}
<tr class="even"><td>{{keys}}</td><td>{{keys2}}</td></tr>
{% endfor %}

Currently your code is packing all the Id and name values into a single flat list. That doesn't work right when you later need to iterate over it, as you want two values per iteration and you're only getting one.
While there are some ways to iterate over pairs from a list (e.g. zip(*[iter(x)]*2)), I would suggest that you just build a list of tuples directly.
Try changing:
codes.append(planet['#Id'])
codes.append(planet['#name'])
To:
codes.append((planet['#Id'], planet['#name']))

Related

Why python dict is parsed in specific way in django template

I am creating a dict and return to django template
parsing = dict()
for idx,title in enumerate(titles):
link = parsing.setdefault(idx, {})
link.setdefault('title', title)
link.setdefault('image', image)
# print(link['image'])
return render(request, "blog/intro.html", {'parsing':parsing})
But can't understand why only this code works in template. Only with 1. Why?
{% for el in parsing.items %}
{{ el.1.title }}
{% endfor%}
EDIT:
let's say I need to put both title and image as elements of lists to dict. how can I also create list comprehension for images?
titles = [...]
images = [...]
parsing = [{'title': title, 'image': image} for title in titles]

Feeding JSON results from MongoDB into Django Template view doesn't display dictionary values

I'm returning a record set from MongoDB, parsing this as JSON and pushing this into a view and attempting to access dictionary values of each record in a template. I can print the records (as an individual record), but I cannot access the structure of each record as a dictionary. How can I get at the values?
def index(request):
results = settings.vali_collection.find({'index': [] })
json_docs = [json.dumps(doc, default=json_util.default) for doc in results]
return render(request, 'db.html', {'results': json_docs[0:3]})
In my template:
{% for result in results %}
{{ result.name}}
{{ result.items.name}}
{% endfor %}
My JSON looks like:
{"name": "Travel & Leisure", .., ..}
I can print the records in my template with {{record}}, but how do I get at the record as a dictionary? What I have above in the template doesn't work and returns nothing. But when I use:
{% for result in results %}
{{ result}}
{% endfor %}
I can get the records printed out to screen in JSON format. If I print out json_docs I get the following:
['{"name": "random", "sector": "random"}', {"name": "random", "sector": "random"}', {"name": "random", "sector": "random"}']
If the json is a dictionary itself, you need to have nested loops. Something like the following:
{%for i in gme%}
{%for l, k in i.items%}
<p> {{l}} {{k}} </p>
{%endfor%}
{%endfor%}
gme looks like this:
gme = [{"sdfje": 'sdfs',"sdfds": "sdf"},...]
The output is:
sdfje sdfs
sdfds sdf
Use json.loads(...) instead of json.dumps.
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
Serialize obj to a JSON formatted str
json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
Deserialize s (a str or unicode instance containing a JSON document) to a Python object using this conversion table.
What you are doing is serializing python dictionary to JSON formatted str, so you get string instead of dictionary.
You need to deserialize and for that, you need json.loads
If you can't use json.loads, as you said in comments section, then the results variable is not a json string. Maybe it is what you are looking for? Try to debug and see what is inside results
If you're using PyMongo 2.8 find returns a Cursor that can be sliced. This should work:
db.test.find()[20:25]
And this should also work:
result = db.test.find()
...
sliced_result = result[20:25]
You don't need to transform the result to JSON, you can transform the Cursor to a list and pass that directly to the template, like that:
def index(request):
results = settings.vali_collection.find({'index': []})[:3]
return render(request, 'db.html', {'results': list(results)})
You need to use list(results) to force the Cursor to execute the query. In your template you'll have a list of dicts, so this should work:
{% for result in results %}
{{ result.name }}
{{ result.items.name }}
{% endfor %}
result should be a dict. The only problem I see is that items is a template function in Django, this might confuse people that are reading your template, and would prevent you from doing something like this:
{% for result in results %}
{% for attr_name, value in result.items %}
{{ attr_name }}: {{ value }}
{% endfor %}
{% endfor %}
The inner for would show every attribute, and their value, of a document in your MongoDB collection.
If you're using an older version of PyMongo that doesn't allow slicing, you may need to do something like this:
def index(request):
results = settings.vali_collection.find({'index': []}).limit(3)
return render(request, 'db.html', {'results': list(results)})
limit limits the number of results returned by the Cursor.
I believe result in the template isn't what you think it is. Let's examine as follows:
In function index(request):
results = settings.vali_collection.find({'index': [] }) returns a list of dictionary-like objects.
json_docs = [json.dumps(doc, default=json_util.default) for doc in results] returns a list of JSON strings (not dictionaries).
So later on when you iterate through the sublist json_docs[0:3], you are just iterating through a list of strings which is why you cannot reference the .name and .items properties.
It looks like what you actually want is a dict() like object for each result in your template. To do this, avoid dumping the dictionaries into JSON.
So instead of:
# WRONG:
json_docs = [json.dumps(doc, default=json_util.default) for doc in results]
return render(request, 'db.html', {'results': json_docs[0:3]})
# /WRONG
...just pass the result in directly:
results = settings.vali_collection.find({'index': [] })
results = list(results) # This may or may not be necessary, depending on what mongo client you're using
return render(request, 'db.html', {'results' : results[:3])
Then in your template, when you iterate through results, each result should be a dictionary-like object which you can use result.name or result.items on.
BTW, the result.items.name reference in your code looks a bit weird to me (like it would return an error), but it's hard for me to debug without knowing what each record looks like.
Change your view like this
def index(request):
results = settings.vali_collection.find({'index': [] })
return render(request, 'db.html', json.dumps({"results":results[0:3]}))
You can now use your for loop to render

Django Displaying Menu/Sub Menu

I am trying to displaying Menu and Sub Menu in table format like
Menu1
Menu2
SubMenu1
SubMenu2
SubMenu3
Menu3
SubMenu4
SubMenu5
SubMenu6
Menu4
So far, I was able to come up with below code but its not showing any record.
Views.py
def getCompleteMenuList():
return Menu.objects.getMenuListing(id)
#mainMenuObj=Menu.objects.getMenuListing(id)
return render_to_response('manageMenu.html', {'title': menu_title,'name':name,'mainMenu':getCompleteMenuList,},context_instance=RequestContext(request))
Models.py
def getMenuListing(self, id):
mainMenus = self.filter(parent_menu=0,business=id).order_by('order')
result = []
menus = []
for menu in mainMenus:
menus.append(menu)
submenu = self.filter(parent_menu=menu,business=id).order_by('order')
if submenu.exists():
result.append(submenu)
return dict(zip(menus, result))
template.html
{% with mainMenu.items as pop_menus %}
{% for key, value in pop_menus %}
display main menu rows
{% for data in value %}
display sub menu rows
{% endfor %}
{% endfor %}
{% endwith %}
Current Situation I have 5 rows in table with 4 as parent_menu =0 and 1 as parent_menu = 1 (which exists).
When I try to print mainMenus its show 4 menu object.
< Menu: Menu object >, < Menu: Menu object >, < Menu: Menu object >, < Menu: Menu object >
But when I print menu inside for loop it only print 1 Menu object
Menu object
Can you please advise what I am doing wrong or is there any other way to achieve same thing?
This is not the right way of accessing your model methods, firstly you have to have an object of the Class which your method belongs to
Ex:
m = Menu.objects.get(id=foo)
foo is just an example it has to be some value corresponding to your id.
Then call the method you created on the models.py file through the object passing the required arguments
Ex:
menus = m.getMenuListing(id)
Now you have the correct data in the variable menus.
Try it this way.
at this line..
return dict(zip(menus, result))
Your menus and result length are not equals and therefore the zip() function as described here..
The returned list is truncated in length to the length of the shortest
argument sequence.
the dictionary will be truncate to length of menus.
Apart from your html template try unit test with getMenuListing() result.

sqlite db called from flask only returns variables, not values

I have a flask app that queries a sqlite db:
#app.route('/<subject_id>')
def subject_id_lookup(subject_id):
entries = query_db('select visitdt, cvnotes from exam where id = ?',
[subject_id], one=True)
return render_template('show_results.html', entries = entries)
I am using flask functions largely unchanged from the docs including query_db()
def query_db(query, args=(), one = False):
"""Queries the database and returns a list of dictionaries"""
cur = g.db.execute(query, args)
rv = [dict((cur.description[idx][0], value)
for idx, value in enumerate(row)) for row in cur.fetchall()]
return (rv[0] if rv else None) if one else rv
Finally here is my show_results.html file:
{% extends "layout.html" %}
{% block body %}
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry }}</h2>
<br>
{% else %}
<li><em>No entry here</em>
{% endfor %}
</ul>
{% endblock %}
The query runs fine but the nothing is returned except the variable names visitdt & cvnotes. When I change the line above to <li><h2>{{ entry.cvnotes }}</h2>, it returns nothing. How can I modify my query to show results from my subject_id_lookup() function?
The issue is that query_db returns different things depending on whether you specify one=True or one=False.
>>> query_db(your_query, [some_id], one=True)
{visittd: "a value", cvnotes: "some notes"}
>>> query_db(your_query, [some_id], one=False)
[{visittd: "a value", cvnotes: "some notes"}] # Note the wrapping list
When you enumerate over a dictionary the result is the keys in the dictionary - when you enumerate over a list, the result is the entries in the list.
>>> for thing in query_db(your_query, [some_id], one=True):
... print thing
visitdt
cvnotes
>>> for thing in query_db(your_query, [some_id], one=False):
... print thing
{visittd: "a value", cvnotes: "some notes"}
If you want to use the same template and you know there is only going to be one value returned for one id (or if you are fine with dealing with more than one value) simply remove the one=True keyword argument in subject_id_lookup. entries will then be a list of one dictionary containing the keys visitdt and cvnotes - when you iterate over it in your template each entry will be a result dictionary (rather than a key in the single result dictionary) and {{ entry.cvnotes }} will work.

How to display string which contains django template variables?

Let's say I have an string variable called *magic_string* which value is set to "This product name is {{ product.name }}" and it's avaible at django template. Is it ever possible to parse that variable to show me "This product name is Samsung GT-8500" instead (assuming that name of the product is "GT-8500" and variable {{ product.name }} is avaible at the same template) ?
I was trying to do something like this, but it doesn't work (honestly ? Im not surprised):
{{ magic_string|safe }}
Any ideas/suggestions about my problem ?
Write custom template tag and render that variable as a template.
For example look at how "ssi" tag is written.
On the other hand, can you render this string in your view? Anyway here is an untested version of that tag:
#register.tag
def render_string(parser, token):
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError("...")
return RenderStringNode(bits[1])
class RenderStringNode(Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
var = context.get(self.varname, "")
return Template(var).render(context)
Perhaps I dont understand your question but what about,
from django.template import Context, Template
>>> t = Template("This product name is {{ product.name }}")
>>> c = Context({"product.name": " Samsung GT-8500"})
>>> t.render(c)
Regards.

Categories

Resources