How to render Kwargs in For Loop with Flask/Jinja - python

I'm trying to print a simple list of strings that I gathered from a sqlite database. I tested the query result and the list is just fine, but to print it with python (inside a for loop) I would need to do print(*element) as printing kwargs.
The problem comes when trying to print it inside a for loop in the Flask template with jinja2. This would print something like <sqlite3.Row at 0x7fe42f0a5710> for every element, and I can't seem to find anywhere which is the right way to do it.
This is my code:
<select>
{% for element in my_list %}
<option value="my_class">{{ element }}</option>
{% endfor %}
</select>
This is the function that sends the list_from_db to the template.
def index():
list_from_db = get_my_list_of_strings()
return render_template('index.html', my_list=list_from_db )
I'll appreciate any help on the matter.

I found a solution for this in another SO answer related with Sqlite .fetchall().
Python's sqlite3 module returns a list of tuples even when querying a single column. This can be prevented applaying the row_factory attribute to the db cursor.
Here is the link to the original answer.
Edit: Although this was really useful and it sent me to the right path, I ended up using the attribute make_dicts.

Related

Sending and rendering HTML syntax via jinja variable

I need some complicated operations to render some dynamic trees in my front-end. But as I can't find any way to run recursion in my jinja or front-end, I take an approach to make a string in my views.py along with HTML syntax and render them in the front-end to get the desired output something like this (As an example, here I skip the original complicated string because there is no need for it):
in views.py:
test = "<h2>Hi This is from django</h2><ol><li>abc</li><li>mno</li><li>xyz</li></ol>"
mydict={
'test' : test,
}
return render(request, 'app\index.html', mydict)
In index.html:
<div class="container-fluid">
{{ test }}
</div>
My desired output with this code is:
Hi This is from
djangoabcmnoxyz
But the obtain output is:
<h2>Hi This is from django</h2><ol><li>abc</li><li>mno</li><li>xyz</li></ol>
Please suggest to me, is there any way to render the jinja string variable along with the effect of HTML in my front-end? If not then how can I take an approach to render any tree dynamically in my front-end where the level, leaf node, intermediate node, etc all info come from the database.
You can use the django-template-filter safe for this.
{{ test | safe }}

Setting Flask dictionary value via Jinja

If I was to use the following in my Jinja template:
{% set data['enabled'] = True %}
I receive the error TemplateSyntaxError: expected token '=', got '['. Setting one word variables is fine, but as the error states, setting dictionary values through Jinja brings an error.
Is there a workaround for this issue? Thanks.
Jinja2 tries to limit assignments in its code to remove the logic from the view (check out an MVC explanation).
If you still want to do an assignment you will have to use update with a do block. For this you have to enable Expression Statements. After that you can try something like this:
{% do data.update({'enabled':'True'}) %}

How to iterate a dynamic variable in a Django template

Some slightly related questions have been asked about this, but the answers did not really help me. When I tried to implement a potential good hint suggested elsewhere (custom templates), I did not get the desired results.
In my template, I am iterating over a set of keys from a dictionary. The dictionary itself originates from submitting a Django formset.
XML Template snippet: (I am rendering to an XML file)
{% for x in range %}
<file type="{{ form-'x'-type }}" viewpath="{{ form-'x'-file }}"/>
{% endfor %}
The above obviously does not work. The iteration works. The rangevariable is a python argument corresponding to range(int(request.POST['form-TOTAL_FORM'])) passed from the view to the XML template.
At every iteration in the template, I need {{ form-0-type }}, {{ form-1-type}}, {{ form-2-type }}, etc.
How do I do that? If I really need to use a custom filter for this, how do I do this?
I hope this question (and the answers) will help many having the same problem.
Thanks.
Edit:(Dictionary posted)
<QueryDict:
{
u'form-MAX_NUM_FORMS': [u'1000'],
u'form-INITIAL_FORMS': [u'0'],
u'form-TOTAL_FORMS': [u'2'],
u'form-0-type': [u'1'],
u'form-1-type': [u'2'],
u'csrfmiddlewaretoken': [u'LpkjdDcqRCL4VPM0SAuU7efgZjgeubTN']
}>
Additional note:
In a second view, I lookup the values for the foreign keys and put the values in another dictionary, which I send to my XML template.
Snippet of the code that does this:
detailed_request = {}
for x in range(0, int(request.POST['form-TOTAL_FORMS'])):
detailed_request['form-'+str(x)+'-type'] = Upload_Type.objects.get(pk=request.POST['form-'+ str(x)+'-type'])
detailed_request['form-'+str(x)+'-file'] = request.FILES['form-'+str(x)+'-file']
The above is a working snippet. When I trace detailed_request, I have all the information I need:
{
'form-1-type': <Upload_Type: malib>,
'form-0-type': <Upload_Type: axf_file>
}
Just in case somebody has the same problem, I actually changed the way I do things.
I do not iterate the formset in the template. Instead, I implemented the solution from Paolo Bergantino here:
Dynamically adding a form to a Django formset with Ajax
Then in my views, I simply get every data I need from request.FILES
I hope that helps anybody who started with the same wrong approach.
You can access the for loop helper variables through the following variables
forloop.counter The current iteration of the loop (1-indexed)
forloop.counter0 The current iteration of the loop (0-indexed)
More at: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
So you'd do...
{{ form }}-{{ forloop.counter }}-{{ type }}

two or more dots in a django template after the variable

In a django template, is it possible to have two (or more) dots after a variable? For example, say I have a list of objects that I first want to use a list-index lookup for and then once I have the object, I want to call its method for getting the absolute url, should that work?
For example:
{% for entry in myList %}
{{ entry.0.get_absolute_url }}
{% endfor %}
So the 0 is asking for the first item in the list which is an object, then I want to get the absolute url. It doesn't work when I try it but it doesn't return an error either. Is there a better way to accomplish what I'm trying to do?
To clarify it, what's strange is that:
This works:
{{ singleObject.get_absolute_url }}
In that case if I just try {{ singleObject }}, I get the unicode value of that object so something like: John Smith
This doesn't work:
{% for object in objectList %}
{{ object.get_absolute_url }}
{% endfor %}
But in this case, if I put in {{ object }}, I no longer get the unicode value. I get: [<Name: John Smith>] (name being the name of the model)
Basically, the method works when it's outside of a loop. Could there be any reason for that?
more than one dot absolutely works.
based on your comment, there is no entry.0 because entry IS the first item in the list cause you are already looping through `myList'
just use entry.get_absolute_url instead
but if you only want to print out the url for the first entry, forgo the for loop and just use myList.0.get_absolute_url
UPDATE:
there's a tip from 'the pragmatic programmer' that says:
``select’’ Isn’t Broken
It is rare to find a bug in the OS or the
compiler, or even a third-party product or library. The bug is most
likely in the application.
i think you assumed that django templates were behaving weird, when the truth is you were not building your list correctly. don't be afraid to show some of your actual code, by abstracting the problem for us, you removed the part that included the problem
I got it. I had brackets around each item in my list like so:
objectList = [['John Smith'], ['Jim Jones'], ['Bill White']]
Silly me! Thanks so much for your all your input
What you are doing is perfectly acceptable in Django templates. There is no better way to accomplish what you're trying to do.

Google appengine string replacement in template file

I'm using google appengine (python, of course :) ) and I'd like to do a string.replace on a string from the template file.
{% for item in items %}
<p>{{ item.code.replace( '_', ' ' ) }}</p>
{% endfor %}
But that isn't working. So we cannot execute anything other than basic checks in the app engine templates. Is that Correct ?
Another related problem is I'm trying to shorten a string and make it available to the template.
Each furniture object has a name and a longer description field. In this view I'm rendering, I want only the first 50 characters of the description field.
So I tried something like
items = db.GqlQuery( 'select * from furniture' )
# edit: if you change the above line to
# items = db.GqlQuery( 'select * from furniture' ).fetch( 1000 )
# the .fetch() command makes the addition of dynamic properties work!
for item in items :
item.shortdescr = item.description[ 0:50 ]
# pass data off to template for rendering
self.response.out.write(
template.render( 'furnitureAll.html', { 'items' : items } )
)
Template goes
{% for item in items %}
<p>{{ item.name }}</p>
<p>{{ item.shortdescr }}</p>
<!-- items.shortdescr does not exist here,
probably because I did not .put() it previously. -->
{% endfor %}
Since that didn't work, I tried changing the Gql Query to shorten the string instead. But I'm quickly realizing Gql isn't like SQL. I'm trying to write queries like
select name,LEFT( description, 50 ) from furniture
With little success
I have little experience with Google AppEngine, but my understanding is that it is very closely related to Django. Your templates do not actually contain Python code, even if some of the structures you use in them look like it.
Both of your questions should be solved using template filters. If it was Django, I would use something like this for your second question:
{{ item.description|truncatewords:10 }}
For your first question (string replace), there may be no built-in filter you can use for that. You will need to write your own. Something like this;
from google.appengine.ext.webapp.template import create_template_register
register = create_template_register()
#register.filter
def replace_underscores(strng):
return strng.replace('_', ' ')
Then, in your template, you can do this:
{{ item.code|replace_underscores }}
Apart from the argument-less .fetch() call in your code, which I believe can't possibly work (you ALWAYS have to pass fetch an argument -- the max number of entities you're willing to fetch!), I can't reproduce your problem -- assigning a new attribute (including one obtained by processing existing ones) to each item just works fine in my tests.
Can you please reproduce your observed problem in as tiny as compass as possible and edit your question to include all relevant files pls? Seems to be the only way we could help you with your weird observed bug!
BTW, select name,LEFT( description, 50 ) or whatever OF COURSE won't work in GQL -- GQL, very very explicitly, ONLY supports select * to get whole entities, or select __key__ to get just the entities' keys -- that's all; NO selectivity of columns in the select, much less any OPERATIONS on them!-)

Categories