How can I access nested JSON object in Django Template properly? - python

I'm trying to access some info with dot notation but I'm getting a weird error. I'll try to explain as well as I can with my code.
My relevant code from views.py file:
def index(request):
// removed "x" assignment as it is long an irrelevant
month = (datetime.datetime.now()).strftime("%B")
year = str(datetime.datetime.now().year)
customers = table(x, month, year)
return render(request, 'index.html', {'customers': customers, "month" : month, "year": year})
Here, I call my tablequery file with table function to return a JSON object of files I have from MONGODB(I am not using MONGODB as the default DB so I do it manually). My table function is as follows:
def table(user, month, year):
///// Code to access DB removed
curs = col.find()
list_curs = list(curs)
liststring = json.dumps(list_curs)
liststring = re.sub("_", "", liststring) // have to remove _ from "_id" because template doesnt allow "_id" type of variable to be used with dot notation
jt = json.loads(liststring)
return jt
Type of "jt" appears to be "list" in python when I print it.
My relevant html code:
<tbody>
{% for customer in customers %}
<tr class="gradeX">
<td>{{ customer.id }}</td>
<td>{{ customer.isim }}</td>
<td>
{% for ekran in customer.ekranlar %}
<li>
{{ ekran }} DENEME
{{ customer.ekranlar.1.hesapbakiyeTL}} TL
{{ customer.ekranlar.1.yurtdisibakiyedolar}} USD
{{ customer.ekranlar.1.yurtdisibakiyeeuro }} Euro
</li>
{% endfor %}
</td>
<td>{{ customer.temsilci }}</td>
<td>
<li>{{ customer.toplambakiyeTL }} TL</li>
<li>{{ customer.toplambakiyeUSD }} USD</li>
<li>{{ customer.toplambakiyeEURO }} EURO</li>
</td>
<td> </td>
<td>
<i class="md md-delete"></i>
<i class="md md-edit"></i>
</td>
</tr>
{% endfor %}
</tbody>
Problem lies within the second for-in loop. When I write "ekran" in customer.ekranlar, I only get the "1", "2", "3" etc as output, but not the values for those. There are more variables within those nested objects(? maybe not objects) but I can only access them if I do "customer.ekranlar.1.hesapbakiyeTL" but when I do "ekran.hesapbakiyeTL"(because I need them looped an printed in table cell) I dont get anything because "ekran" is only "1" or "2" or whatever else the name of the "ekran" is but not the values inside.(I have 4 different accesses as tests to see what is visible how, so it's not the final form)
What I think it should be is like I said, "ekran.hesapbakiyeTL" should be able to access that value, but "ekran" only gets the key, not the nested keys/values inside it. I tried so many different things, tried to change the tablequery output type but I get different problems that way, tried to us "forloop.counter" to use as index to access directly as "customer.ekranlar.forloop.counter" but it appears variables cannot be used in dot notation and many others I've forgotten in the last week. Please, I've been stuck trying to access those values within the for-in loop which stops me from going forward with my project and add other functions.
An example document directly from MongoDB Compass app:
Image for data example
Blues: float numbers
Blacks: strings
There can be more in "ekranlar" as in 1, 2, 3...
All help is appreciated.
Thank you all and have a good day
edit1: I tried to get nested values seperately from python. Same things happens. As soon as I use a second for loop to access like "{{ for ekranlar in customer.ekranlar }}, I only get the key values, not the other variables or their content inside
edit2: How I got around it is that I created a custom tag and sent the customer info to a python file in templatetags with forloop.counter and returned needed info that way. Feels a little clunky but works so meh... If anyone gets around to why this happens inside template html, I'd still love to hear it.

Related

Is there a way to have parallel for loops in HTML?

I am using Python FLask to build a webapp and I am trying to push a nested list to a table in HTML.
Python
item = [[22-03-20, $1409.50, 22-03-20], [22-03-20, $60.00, 22-03-20]]
current HTML
{% for rows in item %}
<tr>
<th scope="row">•</th>
{% for cell in rows %}
<td>{{cell}}</td>
{% endfor %}
<td>edit</td>
</tr>
{% endfor %}
The reason for a duplicate of dates in the nested list is because I need to create a special route page to the date itself.
Output I want to achieve
Basically, the edit will redirect to the page to the respective date. As I have multiple expenses of the same date, I can't just use the unique id within the table.
PROBLEM
The current HTML I have is able to output the 3 items I need, date, expense, date but I can't put a URL redirect to the 3rd variable, date. Is there a way to have 2 for loops running parallel to each other, so I could go through 2 lists at the same time? or is there a better way to do what I want to achieve?
Found a way looking through the documentation again, don't need a parallel for loop actually. I changed the nested list to a tuple in a list. Not sure if this is the best way to do it though.
Python
item = [(22-03-20, $1409.50, 22-03-20), (22-03-20, $60.00, 22-03-20)]
HTML
{% for x,y,z in item %}
<tr>
<th scope="row">•</th>
<td>{{x}}</td>
<td>{{y}}</td>
<td>edit</td>
</tr>
{% endfor %}
I think you should use a list of maps.
item = [
{
'date':'22-03-20',
'price':'$1409.50',
'href':'URI'
},
{
'date':'22-03-20',
'price':'$60.00',
'href':'URI'
},
]
so,
{% for row in item %}
<tr>
<th scope="row">•</th>
<td>{{row.date}}</td>
<td>{{row.price}}</td>
<td>
edit
</td>
</tr>
{% endfor %}

How do I access a Python created dictionary

I have followed the code here https://learn.microsoft.com/en-us/outlook/rest/python-tutorialnd and it works however I need to access the calender events for my own purpose.
context = { 'events': events['value'] }
return render(request, 'tutorial/events.html', context)
The HTML is
<table class="table">
<tr>
<th>Subject</th>
<th>Start</th>
<th>End</th>
</tr>
{% for event in events %}
<tr>
<td>{{ event.subject }}</td>
<td>{{ event.start.dateTime }} ({{ event.start.timeZone }})</td>
<td>{{ event.end.dateTime }} ({{ event.end.timeZone }})</td>
</tr>
{% endfor %}
</table>
My question is how can I interrogate context to obtain the data in the format shown above? Ie subject start date time and end date time.
I'm very new to Python.
I've seen how the data is held using debug statements.
See above
I need interrogate context to obtain the data in the format shown above? Ie subject start date time and end date time.
The data in Context looks like this
context data
How does the data get interpreted by the HTML?
From understanding the code above, events['value'] seems like a list of dictionaries. In the python code, you should be able to access it using
for inner_dict in events['value']:
print(inner_dict["subject"])
print(inner_dict["start"]["dateTime"])
print("*****")
The HTML code perhaps interprets it using Template Engine what does {% %} mean in html

How can I separate text from a query result in html?

I'm trying to display the result of a query in a HTML page on django. I'm getting the result expected but I would like to separate the information from a cell in 5 cells. For example: enter image description here.
Since this is a table, I would like to dispose this like 9030101 | 'Registo....' | 165.0 | \65.0 | None.
Sorry if the question is silly but I can't fix this.
<tr>
{% for val in response_data %}
<td>{{val.name}}</td>
{% endfor %}
</tr>
This is a simple way to loop the data and display it in table
Try this
var string = `(9030101,'REGISTO ELECTROCARDIOGRAPICO TRANSESOFAGICO - PEDIATRICO',165.0,165.0,None)`;
var regex = new RegExp(/[^',(0-9)(none)][a-zA-Z- ]*/g);
var finalText;
finalText = regex.exec(string);
alert(finalText)
Happy coding :)
Your question is quite incomplete, so I can only answer based on a couple assumptions.
The main assumtion is that "the result of a query" is a queryset or list (or any iterable) of tuples, each one representing one database row - if that's not the case then for GodOrWhoeverYouBelieveIn's sake, please edit your question wih all relevant details.
The second assumptions is that this list or queryset or whatever is named "results" in your template's context (if that's not the case etc etc...)
Then all you need are two nested loops - the outer one on results to get each row, the inner one on each row to get fields:
<table>
{% for row in results %}
<tr>
{% for field in row %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>

Cannot access python dictionnary keys in django template

"Simple" problem here which would already be solved in a view... But I didn't find a way to do it.
So here is the idea; I have Anonymous1, Anymous2... Anymous3 who received calls and communications times on phone numbers. I want to do for each of them a table like that :
Number | Calls | Communication time
2-xxx-x 1 01:00:00
3-xxx-x 23 00:30:00
total 24 01:30:00
Number of calls, communication time and total are all computed in the view, as it has to be dedicated to. I have a list of dictionnaries which contains all the numbers with the numbers of calls, the communication time and its owner. It is looking like that :
list = [{'number':2-xxx-x ,'owner':Anonymous1' ,'calls':1 ,'communication time':datetime object},...]
Why a list of dictionnaries ? Because I am using the regroup template tags as described in the documentation: https://docs.djangoproject.com/fr/1.9/ref/templates/builtins/#regroup
I also make a dictionnary which contains only the total number of calls, the total communication time and the owner; I am using it to compute the sum of each column. Here is it how it looks like :
second_dict = {'Anonymous1':{'calls':24,'communication_time':datetime object}}
To access them, I am using loops in my html code, which is where I have a problem. To create the table, I am regrouping the list of dictionnaries by their owner and performing loops and I am using the dictionnary to make th:
{% regroup list by owner as owner_list %}
{% for owner in owner_list %}
<table class="display" cellspacing="0" style="position: relative; left: -250px;">
<caption> {{owner.grouper}}</caption>
<thead>
<tr>
<th> {% trans "Number" %} </th>
<th> {% trans "Calls"%}</th>
<th> {% trans "Communication time" %}</th>
</tr>
</thead>
<tbody>
{% for item in owner.list%}
<tr>
<td>{{item.number}}</td>
<td>{{item.calls}}</td>
<td>{{item.communication_time}}</td>
</tr>
{% endfor %}
<tr>
{% with owner.list.0.owner as owner_name %}
<td><b>{% trans "Total" %}</b></td>
<td>{{second_dict.owner_name.calls}} </td>
<td> {{second_dict.owner_name.communication_time}} </td>
{% endwith %}
</tr>
</tbody>
</table>
{% endfor %}
As you can see with the code, I want to access the second dictionary values with owner as a key, following what is described here : https://docs.djangoproject.com/en/dev/ref/templates/api/
The problem is... this is not working at all ! I was thinking it was a str/unicode problem, but moving from one to the other when creating the different dictionnaries in the python views did not change anything.
Anyone got an hint on how to solve this ?
You cannot do lookup in a dictionary in template using a variable, dict in template would always treat what's after the dot as a string lookup like second_dict['owner_name']. You need to write a template filter to do it. Check django doc on how to write custom filter.

django template question (accessing a list)

I am writing a template for my first django website.
I am passing a list of dictionaries to the template in a variable. I also need to pass a few other lists which hold boolean flags. (Note: all lists have the same length)
The template looks something like this:
<html>
<head><title>First page</title></head><body>
{% for item in data_tables %}
<table>
<tbody>
<tr><td colspan="15">
{% if level_one_flags[forloop.counter-1] %}
<tr><td>Premier League
{% endif %}
<tr><td>Junior league
<tr><td>Member count
{% if level_two_flags[forloop.counter-1] %}
<tr><td>Ashtano League
{% endif %}
</tbody>
</table>
{% endfor %}
</body>
</html>
I am getting the following error:
Template error
In template /mytemplate.html, error at
line 7 Could not parse the remainder:
'[forloop.counter-1]' from
'level_one_flags[forloop.counter-1]'
I am, not suprised I am getting this error, since I was just trying to see if would work. So far, from the documentation, I have not found out how to obtain the items in a list by index (i.e. other than by enumeration).
Does anyone know how I may access a list by index in a template?
In short, Django doesn't do what you want.
The for loop has a number of useful properties within a loop.
forloop.counter The current iteration of the loop (1-indexed)
forloop.counter0 The current iteration of the loop (0-indexed)
forloop.revcounter The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed)
forloop.first True if this is the first time through the loop
forloop.last True if this is the last time through the loop
forloop.parentloop For nested loops, this is the loop "above" the current one
You could probably use forloop.counter0 to get the zero-based indexes you want; unfortunately, the Django template language doesn't support variable array indexes (You can do {{ foo.5 }}, but you can't do {{ foo.{{bar}} }}).
What I usually do is to try and arrange the data in the view to make it easier to present in the template. As an example, for you could create an array in your view composed of dictionaries so that all you have to do is loop through the array and pull exactly what you need out of the individual dictionaries. For really complicated things, I've gone so far as to create a DataRow object that would correctly format the data for a particular row in a table.
You use the dot-operator to index the array, or, really, to do anything.
Technically, when the template system
encounters a dot, it tries the
following lookups, in this order:
* Dictionary lookup
* Attribute lookup
* Method call
* List-index lookup
I don't believe you can do math on the index. You'll have to pass in your array constructed in some other way so that you don't have to do this subtraction.
Try using "slice" to access a list by index
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#slice
Perhaps a better way is to use forloop.last. Of course, this will require that you send to the template the specific level_one_flag and level_two_flag out of the level_one_flags and level_two_flags arrays, but I think this solution keeps a better logical separation between view and template:
<html>
<head><title>First page</title></head><body>
{% for item in data_tables %}
<table>
<tbody>
<tr><td colspan="15">
{% if forloop.last and level_one_flag %}
<tr><td>Premier League
{% endif %}
<tr><td>Junior league
<tr><td>Member count
{% if forloop.last and level_two_flag %}
<tr><td>Ashtano League
{% endif %}
</tbody>
</table>
{% endfor %}
</body>
</html>

Categories