Django adding spaces and quotation marks when pushing string to template - django

I've tried to build a table in the view and push it out to the template for that view, because doing it in the template isn't proving to be feasible. I can generate a string that has the correct information in it, but when that template variable is evaluated in the browser, there are extra quotation marks and spaces that seem to keep the table from being correctly produced.
Here is the code from the view:
for unique_activity in uniquelist:
currentrow = '<tr data-activityID="' + str(unique_activity[0])+ '">' + '<td>' + str(unique_activity[1]) + '</td>'
for visit in visits_list:
for activity in visit.activity_set.all():
if activity.id == unique_activity[0]:
currentrow = currentrow + '<td>' + 'Reps:'+ str(activity.Repetitions) + '</td>'
else:
noact = True
if noact == True:
currentrow = currentrow + '<td></td>'
currentrow = currentrow + '</tr>\n'
tablerows.append(currentrow)
table = '<table>'
for row in tablerows:
table = table + row
table = table + '</table>'
table = str(table)
The output is what it needs to be.. an example <table><tr data-activityID="1"><td>Initial Evaluation</td><td>Reps:None</td><td></td><td></td></tr> <tr data-activityID="3"><td>Cold Pack</td><td></td><td>Reps:None</td><td></td></tr> <tr data-activityID="6"><td>Recumbent Exercise Bike</td><td>Reps:12</td><td></td><td></td></tr> <tr data-activityID="7"><td>Leg Press</td><td></td><td></td></tr> <tr data-activityID="8"><td>Shoulder Ladder</td><td></td><td></td></tr> </table>
However, this is what shows up in the DOM, all that I output to the template is simply {{ table }} and this is what gets output into the DOM info,
and results in just the string being displayed, not a table.
Here is the template snippet
<body>
{% if activity_list %}
<table>
{% for activity in activity_list %}
<tr>
<td>{{ activity.ActivityType.Name }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{{ table }}
</body>
I have no idea what is up...

This sounds like you may have autoescape on in your base template (or elsewhere). If you want your variable to be included as HTML and not safely escaped into text, you'll have to either turn autoescape off around it, or mark it with the safe template filter. Here's an example template to try and illustrate.
<p>The following table should be rendered as escaped safe text.</p>
{{ table }}
<p>But with the safe filter, it will be rendered as html!</p>
{{ table|safe }}
<p>And maybe, I want to do this to a few things or have a block of safe html, so I'll just turn the autoescape off for a bit!</p>
{% autoescape off %}
{{ table }}
{{ some_other_safe_html }}
{% endautoescape %}
Using the snippet you provided, here's the code with the safe escape:
<body>
{% if activity_list %}
<table>
{% for activity in activity_list %}
<tr>
<td>{{ activity.ActivityType.Name }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{{ table|safe }}
</body>

Related

Get Data Problem with Foreignkey Models QuerySet (Django)

I am making django practising. I found a repo and edited to myself. When i came to the get data from models with foreignkey, i get query instead of data. I think my function is a little bit spagetti or my template file.
Full repo is here https://github.com/eseymenler/demo2
Here is the output of my codes. First red square is query, but i want second red square datas.
Hasta Adı: {{ patient.name }}
Hastanın Sağlık Problemi: {{ prob }}
Hastanın Boyu: {{ vital }}
Hastanın Sigara Kullanım Durumu: {{ social }}
First data {{ patient.name }} is very good for me. Thats what i want.
But when i get write {{ prob.problem }} it gives me nothing. So where is my fault.
But also when i make for loop like this, i get data which i want. So how can i fix this.
{% for y in prob %}
{{ y.problem }}
{% endfor %}
And my views.py
#login_required()
def patienttumbilgiListView(request, id):
patient = Patient.objects.get(aadhaarId = id)
prob = ProblemList.objects.filter(patient = patient)
vital = VitalSign.objects.filter(patient = patient)
social = SocialHistory.objects.filter(patient = patient)
return render(
request, 'patient_records/patient-problem-tum.html',
context={'prob': prob, 'vital': vital, 'social': social, 'patient': patient })
and my template file
{% extends 'base.html' %}
{% load static %}
{% load bootstrap4 %}
{% load i18n %}
{% block title %}problem-list-view{% endblock title %}
{% block content %}
<div class="container">
Hasta Adı: {{ patient.name }}</br>
Hastanın Sağlık Problemi: {{ prob }}<br>
Hastanın Boyu: {{ vital }}<br>
Hastanın Sigara Kullanım Durumu: {{ social }} <br></div>
<br>
<br>
<div class="container">
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-0lax{text-align:left;vertical-align:top}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-0lax">Hasta Adı:</th>
<th class="tg-0lax">{{ patient.name }}</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0lax">Hastanın Sağlık Problemi:</td>
<td class="tg-0lax">{% for y in prob %}<br> <br> {{ y.problem }}<br> <br> <br>{% endfor %}</td>
</tr>
<tr>
<td class="tg-0lax">Hastanın Boyu:</td>
<td class="tg-0lax">{% for x in vital %}<br> <br> {{ x.height }}<br> <br> <br>{% endfor %}</td>
</tr>
<tr>
<td class="tg-0lax">Sigara Kullanımı:</td>
<td class="tg-0lax">{% for item in social %}<br> <br><br> {{ item.tobacco_smoking_status }}<br> <br> <br>{% endfor %}</td>
</tr>
</tbody>
</table>
</div>
<br>
<br>
{% endblock %}
Roughly What You Had
So your code is:
#login_required()
def patienttumbilgiListView(request, id):
patient = Patient.objects.get(aadhaarId = id)
prob = ProblemList.objects.filter(patient = patient)
vital = VitalSign.objects.filter(patient = patient)
social = SocialHistory.objects.filter(patient = patient)
return render(
request, 'patient_records/patient-problem-tum.html',
context={'prob': prob, 'vital': vital, 'social': social, 'patient': patient })
{% for y in prob %}
{{y.problem}}
{% endfor %}
{% for x in vital %}
{{x.height}}
{% endfor %}
{% for item in social %}
{{item.tobacco_smoking_status}}
{% endfor %}
Some Friendly Suggestions
"id" is a reserved word / function - I suggest changing id to maybe pid in your code.
Return an error to your view - You don't necessarily have to make this change, but I think its a good idea, and can even help with troubleshooting. I mean you should probably be returning an error or something to this chart if you can't find these objects with those ids in your database.
"get()" throws a DoesNotExist error if the id isn't found - You should catch the error and return it to the console you are making or do something like that.
views.py
#login_required()
def patienttumbilgiListView(request, pid):
context = {}
try:
patient = Patient.objects.get(aadhaarId = pid)
except DoesNotExist:
context['error'] = f"Could not find patient with id '{pid}'."
else:
context['prob'] = ProblemList.objects.filter(patient=patient)
context['vital'] = VitalSign.objects.filter(patient=patient)
context['social'] = SocialHistory.objects.filter(patient=patient)
context['patient'] = patient
return render(request, 'patient_records/patient-problem-tum.html', context=context)
template.html
{% if error %}
{{error}}
{% endif %}
{% for y in prob %}
{{y.problem}}
{% empty %}
Could not find problems.
{% endfor %}
{% for x in vital %}
{{x.height}}
{% empty %}
Could not find vitals.
{% endfor %}
{% for item in social %}
{{item.tobacco_smoking_status}}
{% empty %}
Could not find socials.
{% endfor %}
What Your Problem Is And How To Solve It
I am making django practising. I found a repo and edited to myself. When i came to the get data from models with foreignkey, i get query instead of data.
Based on this quote, I am assuming you want to know why the data is being returned as a queryset instead of as a singular result. From the docs:
filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element. If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly: one_entry = Entry.objects.get(pk=1).
Which is why you should use the for loop in your template.html. If you don't want to use that, then you should preprocess this data either by using get() instead of filter() or simply, in the context, send the [0] element to the template from your view.
So, to clarify, if you want to use {{prob.problem}} in your template, you need to change your view to either do prob = ProblemList.objects.filter(patient = patient)[0] or prob = ProblemList.objects.get(patient = patient). If you choose the first, you should check the length (prob = prob[0] if len(prob) == 1 else None), otherwise, if you choose the latter, you should wrap it with a try, except, else clause like this:
try:
prob = ProblemList.objects.get(patient=patient)
except DoesNotExist:
context['error'] = "Could not find ProblemList."
print("Does Not Exist")
else:
context['prob'] = prob
or you could just use the for loop that you have in place, I don't know how many entries you are expecting the query set to have per patient.
If I need to further clarify anything, please let me know.

Django template jinja for loop

Can someone suggest me how to iterate a dictionary in django template?
dic1={5: ['jaw replacement - 23-Jun-2020 (16:20:09.164240)', 'jaw replacement done - 23-Jun-2020 (16:20:51.158085)', 'jaw replacement done,almost done - 23-Jun-2020 (16:25:40.066955)', 'jaw replacement done,almost done 1 - 23-Jun-2020 (16:27:00.355605)', 'jaw replacement done,almost done 2 - 23-Jun-2020 (16:31:35.111660)']}
this is the context i am passing
i need something like this in template
for i in dic1:
print(i)
list1=dic1[i]
for k in list1:
print(k)
{% for i in notes %}
{% with list1=dic1[i] %}
{{list1}}
{% endwith %}
{% endfor %}
This is not working.
Lets say your data is -
dic1 = {'a': [ [1, 2] ], 'b': [ [3, 4] ],'c':[ [5,6]] }
You can use the data.items() method to get the dictionary elements. Note, in django templates we do NOT put (). Also some users mentioned values[0] does not work, if that is the case then try values.items.
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
{% for key, values in dic1.items %}
<tr>
<td>{{key}}</td>
{% for v in values[0] %}
<td>{{v}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
I hope It helps you.
In normal Python you would normally access keys and values by using the items() method on a dictionaty.
For example given the dictionary
some_dic = {'1': 'Hello', '2': 'World'}
You should be able to access this by doing the following:
for key, value in some_dic.items():
print(key, value)
You can follow this same principle in Django templates and simply omit the '()' as follows:
{% for key, value in some_dic.items %}
<h1>Key: {{ key }}</h1>
<h1>Value: {{ value }}</h1>
{% endfor %}
you can pass dic1 one directly to the template from view and iterate through dictionary in template \
in view
return render(request, 'template.html',{'dic1':dic1})
#intemplate.html
{% for key, value in dic1 %}
<tr>
<td> Key: {{ key }} </td>
{% for value_in_array in value %}
<td> Value: {{ value }} </td>
{% endfor %}
</tr>
{% endfor %}

Using function into template (Django/Python)

I'm trying to use a function that compare the keys from headers and datas of a form. If the keys aren't similar, this function adds an empty field.
It works perfectly fine in my views.py :
#Entries define all the datas taken from the fobi forms.
headers = json.loads(entries{0}.saved_data)
headers = headers.items()
for key, value in headers:
for data in entries:
data = json.loads(data.saved_data)
formatted[value] = data.get(key, '')
print(entries)
formatted = formatted.items()
Then i pass formatted into the context and in my template i did :
<tr>
{% for key, valeur in headers %}
<th>
{{ key }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
<tr>
{% for key, valor in headers %}
{% for cle, valeur in formatted %}
{%if cle == valor%}
<td> {{valeur}}</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
</tbody>
The result is perfect, such as every header is aligned with the datas. And if there are some datas missing such as picture, there is an empty sace in this column.
I only printed one form through my loop ( the last saved from the formatted dict). And i want to print all my forms. But it seems impossible in the views.py.
How i manage it into the template ?
Thank you for your answers !
BR, Karro.
I found the solution.
I created a list of dictionnaries :
formattedList = []
Then, i change my initial loop in order to get every dictionnary set in the list :
for entry in entries:
formatted = {}
for key, value in headers:
data = json.loads(entry.saved_data)
formatted[value] = data.get(key, '')
formatted = formatted.items()
**formattedList.append(formatted)**
Finally, i changed these lines in my template file :
<tbody>
**{%for element in formattedList%}**
<tr>
{% for key, valor in headers %}
**{% for cle, valeur in element %}**
{%if cle == valor%}
<td> {{valeur}}</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
Everything worked fine !
I got all my results !

model object not iterable

template.html
{% extends "base.html" %}
<body>
{% block content %}
<form action="." method="post">
{% csrf_token %}
<table align="center" style="margin-left:60px";>
<p>{{KEBReading_form.as_table}}</p>
<tr><td colspan="2" align="right"><input name="KEBsubmit" type="submit" value="Submit Reading" id="_KEBsubmit1"/> </td></tr>
<tr><td colspan="2" >{{KEBMessage}} </td></tr>
</table>
</form>
<table border="1">
<p> KEB Reading as on Month jan and year 2012</p>
<tr>
<th>Date </th>
<th>Time</th>
<th>True Power Reading</th>
<th>Apparent Power Reading</th>
<th>True Power consumed</th>
<th>Voltage Reading</th>
<th>Power Factor</th>
</tr>
{% for item in q2 %}
<tr>
<td>{{item.date}}</td>
<td>{{item.time}}</td>
<td>{{item.truepower_reading}}</td>
<td>{{item.apparentpower_reading}}</td>
<td>{{item.truepower_consumed}}</td>
<td>{{item.voltage_reading}}</td>
<td> {{item.powerfactor}}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
views.py
def KEBReading1(request):
#form2 = KEBReading.objects.all()
if request.method == "POST":
form = KEBReading_form(request.POST)
if form.is_valid():
prevdate=KEBReading.objects.latest("date")
# Model.objects.latest('field')
print prevdate.date
print prevdate.time
# q1 = KEBReading.objects.get(datetime.date.today()-datetime.timedelta(0))
kr_truepower_reading = form.cleaned_data["truepower_reading"]
kr_apparentpower_reading = form.cleaned_data["apparentpower_reading"]
truepower_consumed1=kr_truepower_reading-prevdate.truepower_reading
powerfactor1=((kr_truepower_reading-prevdate.truepower_reading)/(kr_apparentpower_reading-prevdate.apparentpower_reading))
#instance=truepower_consumed,powerfactor
## replace form.save() with following lines
form1=form.save(commit=False)
#form1.calculate(truepower_consumed1,powerfactor1)
form1.truepower_consumed=truepower_consumed1
form1.powerfactor=powerfactor1
print form1.powerfactor
form1.save()
q2=KEBReading.objects.latest("date")
context={'KEBReading_form':form,'q2':q2}
return render_to_response('keb.html',context,context_instance=RequestContext(request))
else:
form = KEBReading_form()
return render_to_response('keb.html',{'KEBReading_form':form},context_instance=RequestContext(request))
i want to display all readings in a table whic i calculated through the views in the template. i get model object not iterable while using for loop to iterate..
A few issues:
First, as Aidan correctly noted KEBReading.objects.latest("date") this will return an object, not a collection or iterable.
Secondly, you aren't assigning any of the fields that you are calculating in view. truepower_consumed1=kr_truepower_reading-prevdate.truepower_reading doesn't assign it to your object that you retrieved (your q2). I'm not sure if this is intentional. However, I suspect you want to return to your template the instance of the form, not another record from the table. You need to update your question.
To fix these problems immediately:
<tr>
<td>{{q2.date}}</td>
<td>{{q2.time}}</td>
<td>{{q2.truepower_reading}}</td>
<td>{{q2.apparentpower_reading}}</td>
<td>{{q2.truepower_consumed}}</td>
<td>{{q2.voltage_reading}}</td>
<td> {{q2.powerfactor}}</td>
</tr>
latest() returns the latest object in the table, not a set of objects. Instead of that, you should use KEBReading.objects.all().order_by('date')
Your q2 variable is just an object not a set.
The following line returns a single object -
KEBReading.objects.latest("date")
But your template is expecting a set that it can iterate over -
{% for item in q2 %}
<tr>
<td>{{item.date}}</td>
<td>{{item.time}}</td>
<td>{{item.truepower_reading}}</td>
<td>{{item.apparentpower_reading}}</td>
<td>{{item.truepower_consumed}}</td>
<td>{{item.voltage_reading}}</td>
<td> {{item.powerfactor}}</td>
</tr>
{% endfor %}
Check the docs for the latest() function.

Using forloop.counter value as list index in a Django template

in my Django 1.1.1 application I've got a function in the view that returns to his template a range of numbers and a list of lists of items, for example:
...
data=[[item1 , item2, item3], [item4, item5, item6], [item7, item8, item9]]
return render_to_response('page.html', {'data':data, 'cycle':range(0,len(data)-1])
Inside the template I've got an external for loop, that contains also another for cycle to display in output the contains of the inner lists of data in this way
...
{% for page in cycle %}
...
< table >
{% for item in data.forloop.counter0 %}
< tr >< td >{{item.a}} < /td > < td > {{item.b}} ... < /td > < /tr >
...
< /table >
{% endfor %}
{% if not forloop.last %}
< div class="page_break_div" >
{% endif %}
{% endfor %}
...
But Django template engine doesn't work with the forloop.counter0 value as index for the list (instead it does if I manually put a numeric value as index). Is there a way to let the list loop works with the external forloop.counter0 value?
Thanks in advance for the help :)
I solved this in a rather inefficient way. Please don't throw up on your computer when you read this code. Given two lists of identical length, it will iterate through the first and print the corresponding item from the second.
If you must use this, only use it for rarely-accessed templates where the length of both lists will be small. Ideally, refactor your template's data to avoid this problem altogether.
{% for list1item in list1 %}
{% for list2item in list2 %}
{% if forloop.counter == forloop.parentloop.counter %}
{{ list1item }} {{ list2item }}
{% endif %}
{% endfor %}
{% endfor %}
You can't use variables for attribute names, dictionary keys or list indices.
Also range(0,len(data)-1] is not valid python. It should be range(len(data)).
You probably don't need cycle. Maybe what you want is this:
{% for itemlist in data %}
...
<table>
{% for item in itemlist %}
<tr>
<td>{{ item.a }}</td>
<td>{{ item.b }} ... </td>
</tr>
...
{% endfor %}
</table>
{% if not forloop.last %}
<div class="page_break_div">
{% endif %}
{% endfor %}
I wanted to have alternating colours in my table using a style sheet, by passing a list of toggling True/False values. I found this really frustrating. In the end I created a list of dictionary items with the same keys as the fields in the table, plus one more with the toggling true/false value.
def jobListView(request):
# django does not allow you to append stuff to the job identity, neither
# will it allow forloop.counter to index another list. The only solution
# is to have the toggle embedded in a dictionary along with
# every field from the job
j = job.objects.order_by('-priority')
# have a toggling true/false list for alternating colours in the table
theTog = True
jobList = []
for i in j:
myJob = {}
myJob['id'] = i.id
myJob['duty'] = i.duty
myJob['updated'] = i.updated
myJob['priority'] = i.priority
myJob['description'] = i.description
myJob['toggle'] = theTog
jobList.append(myJob)
theTog = not(theTog)
# next i
return render_to_response('index.html', locals())
# end jobDetaiView
and my template
{% if jobList %}
<table border="1"><tr>
<th>Job ID</th><th>Duty</th><th>Updated</th><th>Priority</th><th>Description</th>
</tr>
{% for myJob in jobList %}
<!-- only show jobs that are not closed and have a positive priority. -->
{% if myJob.priority and not myJob.closeDate %}
<!-- alternate colours with the classes defined in the style sheet -->
{% if myJob.toggle %}
<tr class=d1>
{% else %}
<tr class=d0>
{% endif %}
<td><a href="/jobs/{{ myJob.id }}/">{{ myJob.id }}</td><td>{{ myJob.duty }}</td>
<td>{{ myJob.updated }}</td><td>{{ myJob.priority }}</td>
<td class=middle>{{ myJob.description }}</td>
</tr>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No jobs are in the system.</p>
{% endif %}
Use forloop.last - True if this is the last time through the loop:
{% if forloop.last %}
{% endif %}
From Built-in template tags and filters