Django - printing multiple passed lists from views.py - python

I have 4 lists with the same length and would like to pass all of them to the html page.
views.py
return render(request, 'result.html', {'listA':listA, 'listB':listB, 'listC':listC, 'listD':listD})
And here is the code when I tried with Flask.
app.py
return render_template('result.html', listA = listA, listB = listB, listC = listC, listD = listD)
Below is the code in the template file; with Flask, it prints out the table without any problems, but it doesn't seem to work with Django.
How should I fix my code?
result.html
{% for i in listA %}
<tr>
<th> {{ listA[loop.index] }} </th>
<td> {{ listB[loop.index] }} </td>
<td> {{ listC[loop.index] }} </td>
<td> {{ listD[loop.index] }} </td>
</tr>
{% endfor %}

You should use a custom templatetag for implementing lookup, because django does not provide one for you.
and then use django template engine for loop for getting forloop.counter0
First create templatetags directory with __init__.py inside your app folder. Lets assume your app is called polls folder structure will look like this:
polls/
__init__.py
models.py
templatetags/
__init__.py
lookup.py
views.py
After write lookup code which goes inside lookup.py:
from django import template
register = template.Library()
#register.filter
def lookup(d, key):
return d[key]
And finlly use it in template file:
{% load lookup %}
...
{% for i in listA %}
<tr>
<th> {{ listA|lookup:forloop.counter0 }} </th>
<td> {{ listB|lookup:forloop.counter0 }}</td>
<td> {{ listC|lookup:forloop.counter0 }}</td>
<td> {{ listD|lookup:forloop.counter0 }}</td>
</tr>
{% endfor %}
...
Ref 1 - Get list item dynamically in django templates
Ref 2 - Custom template tag example
Ref 3 - Django templatetag
Ref 4 - Django template for loop

Related

Django Render List of Dictionaries to a template

I have a list of dictionaries with same key information. How can I pass this list of dictionaries to a Django template ?
listdict = [{'product':'specs','price':'12'}, {'product':'shoes','price':'30'}]
When trying to send this list via views file to template it fails with an error indicating that only dictionaries are allowed.
Here is the code from views file
return render(request, 'recordings/extensionrecording.html',listDict)
Here is the html block-
<tbody>
{%for list in listDict%}
{%for elements in list%}
<tr>
<td class="body-item fonts-style display-4">{{elements.product}}</td>
<td class="body-item fonts-style display-4">{{elements.price}}</td>
</tr>
Just pass these as an entry of the dictionary:
return render(request, 'recordings/extensionrecording.html',{'listDict': listDict})
Then in the template, you can render these with:
{%for item in listDict %}
{{ item.product }}
{{ item.price }}
{% endfor %}

converting and multiply float to int in django templates

I am fetching some data from a stocks API and I get some values (stored in the DB as float)
as follow:
YTD Change 0.379996
daily % change 0.00854
my view is as follow:
def get_stock(request):
empty = True
localStocks = Stock.objects.all()
if len(localStocks) > 0 :
empty = False
return render (request,'get_stock.html',{'empty':empty, 'output':list(localStocks)})
and my template
<section class="section-typography container u-readable">
<table>
<thead>
<tr>
<th>Ticker</th>
<th>Name</th>
<th>Price</th>
<th>Last Time</th>
<th>% Change</th>
<th>52W High</th>
<th>52W Low</th>
<th>YTD Change</th>
</tr>
</thead>
<tbody>
{% if not empty %}
{% for list_item in output %}
<tr>
<td> {{list_item.symbol }}</td>
<td> {{ list_item.companyName }}</td>
<td> {{ list_item.latestPrice }}</td>
<td> {{ list_item.latestTime }}</td>
<td> {{ list_item.changePercent }}</td>
<td> {{ list_item.week52High }}</td>
<td> {{ list_item.week52Low}}</td>
<td> {{ list_item.ytdChange }}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</section>
{% endblock %}
the % change for the stock YTD is not 0.379996 but 37.99% and this is what I would like to display. Similarly the daily change is not 0.00854 but 0.85% . How can I manipulate the date either on the view or template to basically multiply it and display only the first 2 decimals of the float?
You need to implement a custom template tag. In your app directory create a new module named templatetags. Inside this module there should be a blank __init__.py and a random named file like percentage.py.
Your percentage.py should contain:
#percentage.py
from django import template
register = template.Library()
#register.simple_tag(name="percentage")
def percentage(value):
return str(round(value *100,2))+'%'
In any html file you want to use this tag, you should load this tag at the start of the file with {% load percentage %}. In order to pass the required value to the templatetag, you need to use it like: {% percentage list_item.changePercent %}
The best way is to change the value in view as follow:
YTD_to_pass = ((YTD*10000)//1/100)
this will multiply the value by 100 and keep 2 digits after whole number
then simply add a % symbol in template.

Django - how to make a link in an html template open an app and pass a objects value as a parameter

Hello I have an app that displays some database information in a table. Inside of the html template I am making an edit link that I want to open another app(page viewLit) while passing a value to it's view. I have added my code below. My question is I am unsure of how to make this links url and pass the object data located inside circuit.circuitid along with it. I haven't been able to find the right way to code this yet and this is just how I thought that this should be done. If anyone has a better idea I am open to suggestions.
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}
myapp/myapp/urls.py
urlpatterns = [
path('viewLit/', include('viewLit.urls')),
]
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/circuitid.id', views.viewLit, name='viewLit'),
]
myapp/viewLit/views.py
def viewLit(request, circuitid):
#display records fields here
return HttpResponse("You are at the viewLit page!")
Have a look at the documentation:
Django documentation
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/(?P<circuit_id>\w+)', views.viewLit, name='viewLit'),
]
html- template:
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}

URL Patterns and Views

I have an application which requests data based on certain parameters. I use two functions to handle the requests and then create two objects from the responses. I am able to iterate through each object individually and display the data of a particular object on my webpage, but when I try to use both functions simultaneously, only one function iterates through the object. It is my understanding that this issue has something to do with URL patterns, but I am not as to what the best approach would be. Below you will find my urlpatterns, my functions, and the HTML I use to access the view.
urls.py
urlpatterns = [
path('', views.customer, name='customer'),
path('', views.information, name='information'),
]
views.py
def customer(request):
for i, contact in enumerate(contactObj):
try:
contacts = contactObj
context = {'contacts': contacts}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
def information(request):
for i, ticket in enumerate(ticketObj):
try:
tickets = ticketObj
context = {'tickets': tickets}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
home.html
<tbody>
{% for ticket in tickets %}
<tr class="{% cycle 'row1' 'row2'">
<td> {{ ticket.id }} </td>
<td> {{ ticket.company.name }} </td>
<td> {{ ticket.summary }} </td>
</tr>
{% endfor %}
</tbody>
Your URL patterns should be different for every view. otherwise, it will always call the view which is defined above either you call it by customer or information
So your URL patterns should be
urlpatterns = [
path('customer/', views.customer, name='customer'),
path('information/', views.information, name='information'),
]
UPDATE
You don't have to create separate views for fetching objects from different tables to
show in a webpage
Create a single view and send as many objects in context dictionary.
def table_content(request):
...
# fetch objects here from model
contacts = Contact.objects.all()
tickets = Ticket.objects.all()
# set objects to context dictionary
context = {'contacts': contacts, 'tickets' : tickets}
return render(request, 'uccx/home.html', context)
Now in your template, you can easily loop over tickets and contacts
{% for ticket in tickets %}
<tr>
<td> {{ ticket.id }} </td>
...
</tr>
{% endfor %}
{% for contact in contacts %}
<tr>
<td> {{ contact.id }} </td>
...
</tr>
{% endfor %}

Django form field issue with model formset

I'm having an issue with rendering individual form fields in a template. I have a model formset that I'm re-ordering after creation to make displaying a little easier on the template. Nothing too complicated, but rendering the form fields isn't working. You can see in the template where I try and render {{ form.train }}, but nothing shows up in the output. However, the form is definitely there because {{ form.instance.user.name }} works correctly.
I opened up PDB and inspected the form variable that I'm adding into the dictionary, and it says <django.forms.widgets.ScheduleForm object at 0x10c58bc50>. I'm not sure if that helps or not, but I wanted to provide as much info as possible.
The Model Form
class ScheduleForm(ModelForm):
class Meta:
model = models.Schedule
fields = [
'train',
'semi',
'tri_axle',
'flow_boy',
'misc',
'material',
'notes'
]
views.py
formset_fields = ('train','semi','tri_axle','flow_boy','misc','material','notes')
ScheduleFormSet = modelformset_factory(models.Schedule, fields=formset_fields, extra=0)
formset = ScheduleFormSet(queryset=queryset)
# Getting form in the right format
ordered_forms = {}
for form in formset:
# Make sure the job exists on the object
if not form.instance.job.number in ordered_forms:
ordered_forms[form.instance.job.number] = {}
# Make sure the user exists on the object
if not form.instance.user.name in ordered_forms[form.instance.job.number]:
ordered_forms[form.instance.job.number][form.instance.user.name] = []
# Append to correct place.
ordered_forms[form.instance.job.number][form.instance.user.name].append(form)
# Dict will look like
# { 'jobID' : { 'user' : [form1,form2,form3] } }
Template
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users %}
<table class='table striped'>
<thead>
<tr>
<th>{{ user }}</th>
<th>Train</th>
<th>Semi</th>
<th>Tri-Axle</th>
<th>Flow Boy</th>
<th>Misc</th>
<th>Material</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody>
{% for form in forms %}
<tr>
<td>{{ form.instance.broker.name }}</td>
<td>{{ form.train }}</td>
<td>Semi</td>
<td>Tri-Axle</td>
<td>Flow Boy</td>
<td>Misc</td>
<td>Material</td>
<td>Notes</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endfor %}
Turns out I forgot to add .items to {% for user, forms in users %}.
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users.items %}
<table class='table striped'>
....
{% endfor %}
{% endfor %}

Categories

Resources