Prevent rendering the unicode character in django template - django

I am executing a query to a table in my view and I pass the data to the context dictionary:
conn = psycopg2.connect(constr)
cur = conn.cursor()
sqlstr = "SELECT DISTINCT adm0_name FROM wld_bnd_adm0_gaul_2015 ORDER BY adm0_name;"
cur.execute(sqlstr)
countries = cur.fetchall()
ctx['countries'] = countries
Then I want to render the data in my template as following:
{% if countries %}
{% for cntr in countries %}
<li><a href="#" id= {{ cntr }}>{{ cntr }}</a></li>
{% endfor %}
{% endif %}
The problem is that I get a unicode format like this:
[(u'Abyei',), (u'Afghanistan',), (u...
I tried to convert my data in the view to JSON as:
countries = json.dumps(countries)
But actually then when I render the data in the template I get each single character of the JSON string separately.

As mentioned in the docs fetchall returns a list of tuples, so each of the country name is inside a tuple in the list. You need to flatten the list to get list of countries.
countries = cur.fetchall()
countries = [c[0] for c in countries]
ctx['countries'] = countries

I'm assuming you're using Python2.
From the documentation, here's what you would get after calling json.dumps:
>>> json.dumps([(u'Abyei',), (u'Afghanistan',)])
'[["Abyei"], ["Afghanistan"]]'
Since you get a single JSON formatted string serialized from dictionary, when you iterate it, you'll get a character on every iteration. This explains why you get single characters when you render the data.
Your countries is already a dictionary thus can be used without serializing; if you want to convert unicode strings, you can do something like:
>>> countries = [(u'Abyei',), (u'Afghanistan',)]
>>> [(country.encode('ascii','ignore'), ) for (country, ) in countries]
[('Abyei',), ('Afghanistan',)]

Related

How to join two tables into a dictionary in dbt jinja

I want to create a for loop in dbt that loops through two columns of a table in my database and created case when statements using the values in each row of the two columns. Just like this:
{% set locations = {'%United-States%':'United States', '%USA%':'United States'} %}
select
case
{% for feeder, correct in locations.items() %}
when lower(locationname) like {{feeder}} then {{correct}}
{% endfor %}
end as city
from table
I was able to create lists for both feeder and correct, but I am not able to merge them as key-value pairs of a dictionary to loop through it. Any ideas on how should I do this?
Sounds like you have two problems:
fetch data from another table, and
use that data to populate a case when statement.
Big thing to remember is that the main thing that dbt-jinja does is create a string of SQL. That said, there is clever functionality that lets you query a database before jinja starts to put the string together.
The idea being:
fetch the values from the database that you want to have included in your SELECT query
populate the previously fetched values into the query while rendering the statement
there's two macros that may be of use in the first step:
run_query() (docs), and
dbt-utils' get_query_results_as_dict() (docs)
Something like this might work (provided you already have dbt-utils installed:
{% set locations_query %}
select feeder, correct from my_other_table
{% endset %}
{% set locations = run_query(locations_query) %}
select
case
-- not sure how this part will work yet....
{% for feeder, correct in locations.items() %}
when lower(locationname) like {{feeder}} then {{correct}}
{% endfor %}
end as city
from table

How to create 2D list of a database table and evaluate it in a template?

I've got a model class, House, with several columns. I want to get all the entries to this table, with all the columns, and display these on in a table in a template.
Firstly, how do I pull all the information that I need out of the database (and into a 2d list?), and what tag could I use to access specific data in the table?
it's as easy as stated here
so, practically:
all_houses = Houses.objects.all()
will give you all the entries in your database.
from within a view, pass that variable to the template context then, in the template:
{% for house in all_houses %}
{{ house.<column_name> }}
{% endfor %}
let me explain this bit of code: once you pass all your entries to the template, you can loop them with {% for %}
{{ house. }} means that you can extract the value you need from the column you need ( column_name ) and place it wherever you want (from whitin the for loop, obviously) so you can have (for example) {{ house.price }}, {{ house.bathrooms }} and so on, for each entry you have in your "all_entries"

Issues with Fetching the data from database

I can fetch the data like this.
value= mymodel.objects.get(anycondition)
OR
value= mymodel.objects.filter(anycondition)
and can send them to my template with context.
But if I want to select all the data from a table(for all users not only one) as this query does
value= mymodel.objects.all()
and send this value to my template and can see there field by field
e.g.
my table has two fields name and phone no and I use the above query( value= mymodel.objects.all()) now if i want to see all names then i can see that and if i want to see phone no. I can see that too.
I have tried this and it doesn't work and I even I do not know it is possible or not.
If it is possible then please let me know how I can do this ?
I hope you understand my question. !!
Thanks in advance
.all() will return a list of objects that represent the rows in your model. .get() only returns one object. Your template is trying to print the result of all() if it was one object.
This is the same as if you had a list and you wanted to loop through it. In your view you would do:
product = Product_attributes.objects.all()
for i in product:
print i.size
print i.color
The equvalent for the template is:
<ul>
{% for i in product %}
<li>{{ i.size }}</li>
<li>{{ i.color }}</li>
{% endfor %}
</ul>
Although this question isn't clear it seems like you are having a bit of problem with Field Lookups. It is fairly easy to learn Here is a link to get you started

Django: optimizing queries

I want to list the number of items for each list. How can I find this number in a single query, rather than a query for each list?
Here is a simplified version of my current template code:
{% for list in lists %}
<li>
{{ listname }}:
{% with list.num_items as item_count %}
{{ item_count }} item{{ item_count|pluralize }}
{% endwith %}
</li>
{% endfor %}
lists is passed as: List.objects.filter(user=user)
and num_items is a property of the List model:
def _get_num_items(self):
return self.item_set.filter(archived=False).count()
num_items = property(_get_num_items)
This queries SELECT COUNT(*) FROM "my_app_item" WHERE... n times, where n is the number of lists. Is it possible to make a single query here?
You should do this in your view and send the dictionary, instead.
Model.objects.values_list('item').annotate(Count('num_items'))
This will produce the SQL same as, (or equivalent to) the one you have posted.
In the following, I tried to take into account all your constraints: filtering on fields of List, on fields of Item, counting items , and grouping by list.
The solution I see is that you could use values() (here is the django doc about this : http://docs.djangoproject.com/en/dev/topics/db/aggregation/#values)
from django.db.models import Count
lists = list(List.objects.filter(user=user))
items=Item.objects.values(list).filter(archived=False,list__in=lists).annotate(count=Count("id"))
#you will get a list of dicts of the form [{'count':2,'list':5},...] where 5 is the id of the list
#now, you can match you list with you item counts in python
list_items_count_dict={}
for item in items:
list_items_count_dict[item['list']]=item['count']
for list in lists :
list.item_count = list_items_count_dict.get(list.id)
That will make only 2 queries, one for getting the lists, the other for computing the item counts. Afterwards, you will have two loops (that could probably be replaced by list comprehension one-liners ), but only for the lists you are interested in.
afterwards, in your template, you can use
{{list.item_count}}
There might be a more elegant option, but that is what I have found right now. I am also certain that you could reduce the number of query to one by using custom sql.
Disclaimer: I have not tested this code, but I have tested similar code on similar models. You could have problems because list is one of the keyword of the Python language.

Modifying QuerySet result

Is it possible to change some specific items in a QuerySet object? In my case i'm trying to slicing "title" fields with length more than 40 characters and append "..." at the end of field.
There are 2 ways of doing what you want.
The first is to use a Django filter. So if you are looping through the items of your queryset and displaying them on a page use something like truncatewords. You would use this like this in your template:
{% for item in queryset %}
<h1>{{ item.title|truncatewords:3 }}</h1>
{% endfor %}
It doesn't look like there is a Django filter for truncating base on the number of characters. If you want to write your own filter it's not that hard to do.
The other option is to put a method on your model to do what you want. Here is an example:
#property
def short_title(self):
return '%s...' % self.title[:40]
You would then be able to reference this anywhere in your template as {{ object.short_title }}.
I suggest adding a new property 'adjusted_title' to each object
for item in your_query_set:
if(len(item.title) > 40):
item.adjusted_title = item.title[0:40] + "..."