Django loop in html issue - django

i had been trying to solve this problem for almost 3 hrs but i didnt get the result i want,
this is the result i want
this is my current result
this is my html
<table id="blacklistgrid" border="2px">
<tr>
<th>Students Name</th>
{% for student in teacherStudents %}<th >{{student.Date}}</th>{% endfor %}
<th data-id='headers' id='headerave'>Average</th>
</tr>
<tr>
<tbody id="scoreboard">
{% for students in studentname %}
<tr class="tr2">
<td><input type="text" name="students" value="{{student.id}}" id="student" hidden>{{students.Students_Enrollment_Records.Students_Enrollment_Records.Student_Users}}</td>
<tr>
{% endfor %}
</tr>
<tr>
{% for studentss in Students %}
<td class="td" scope="row"><input type="text" name="students" value="{{student.id}}" id="student" hidden>{{studentss.Grade}}</td>{% endfor %}
<td data-id='row' id="ans"><input type='number' class='averages' step="any" name="average" readonly/></td>
</tr>
</tbody>
</table>
this is my views.py
teacherStudents = studentsEnrolledSubjectsGrade.objects.filter(Teacher = teacher).filter(grading_Period = period).filter(Subjects = subject).filter(Grading_Categories = category).filter(GradeLevel = grade).distinct('Date')
studentname = studentsEnrolledSubjectsGrade.objects.filter(Teacher = teacher).filter(grading_Period = period).filter(Subjects = subject).filter(Grading_Categories = category).filter(GradeLevel = grade).distinct('Students_Enrollment_Records')
Students = studentsEnrolledSubjectsGrade.objects.filter(Teacher = teacher).filter(grading_Period = period).filter(Subjects = subject).filter(Grading_Categories = category).filter(GradeLevel = grade)
return render(request, 'Homepage/period.html',{"teacherStudents":teacherStudents,"Students":Students,"studentname":studentname})
my models.py
class studentsEnrolledSubjectsGrade(models.Model):
Teacher = models.ForeignKey(EmployeeUser, related_name='+', on_delete=models.CASCADE,
null=True,blank=True)
GradeLevel = models.ForeignKey(EducationLevel, related_name='+', on_delete=models.CASCADE,
null=True,blank=True)
Subjects = models.ForeignKey(Subject, related_name='+', on_delete=models.CASCADE, null=True)
Students_Enrollment_Records = models.ForeignKey(StudentsEnrolledSubject, related_name='+',
on_delete=models.CASCADE, null=True)
Grading_Categories = models.ForeignKey(gradingCategories, related_name='+', on_delete=models.CASCADE,
null=True,blank=True)
grading_Period = models.ForeignKey(gradingPeriod, related_name='+', on_delete=models.CASCADE,
null=True,blank=True)
#Items = models.IntegerField(blank=True, null=True)
Date = models.DateField(null=True, blank=True)
Grade = models.FloatField(null=True, blank=True)
this is my data in admin.py
can you guys help me in my html loop? do you have suggestions? my database is postgresql
UPDATE just like mr #Chris said in the comment section, I want to create a table with a row per student and in the columns the grades at a specific date, Create the table in your view (e.g. as a list of lists or one annotated queryset) and use the template for rendering but i dont know how, please help me guys,

I would suggest generating the table in your view and the pass it to your template for rendering.
#views.py
def your_view(request):
students = StudentsEnrolledSubjectsGrade.objects.filter(put_in_your_filters).order_by('student_name', 'date').values('student_name', 'date', 'grade')
dates = list(students.values_list('date', flat=True).distinct().order_by('date'))
# table basics
table = []
student_name = None
table_row = None
columns = len(dates) + 1
# table header
table_header = ['Student Name']
table_header.extend(dates)
table.append(table_header)
for student in students:
if not student['student_name'] == student_name:
if not table_row is None:
table.append(table_row)
table_row = [None for d in range(columns)]
student_name = student['student_name']
table_row[0] = student_name
table_row[dates.index(student['date']) + 1] = student['grade']
table.append(table_row)
return render(request, 'my_template.html', {'table': table})
Then you can interate through all the rows of that table in you template:
<table id="blacklistgrid" border="2px">
<tr>
{% for v in table.0 %}
<td>{{ v }}</td>
{% endfor %}
</tr>
<tbody>
{% for row in table|slice:"1:" %}
<tr>
<td>{{ row.0 }}</td>
{% for c in row|slice:"1:" %}
<td>{{ c }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
You need to adapt that to your needs, it is just to give you an idea

Related

Django initial loading of page taking too long

Hi I am a beginner at Django and I am working on a project that lists 100 companies in each page along with there contacts and also the amount of items sold. Here is an example:
As you can see the initial loading time of the page is very high. But when I refresh the page it refreshes very fast because I am using caching.
Here are some of my other files:
models.py
from __future__ import unicode_literals
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=150)
bic = models.CharField(max_length=150, blank=True)
def get_order_count(self):
orders = self.orders.count()
return orders
def get_order_sum(self):
orders = Order.objects.filter(company=self)
total_sum = sum([x.total for x in orders])
return total_sum
class Meta:
ordering = ['-id']
class Contact(models.Model):
company = models.ForeignKey(
Company, related_name="contacts", on_delete=models.PROTECT)
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150, blank=True)
email = models.EmailField()
def get_order_count(self):
orders = self.orders.count()
return orders
class Order(models.Model):
order_number = models.CharField(max_length=150)
company = models.ForeignKey(Company, related_name="orders", on_delete=models.CASCADE)
contact = models.ForeignKey(Contact, related_name="orders", on_delete=models.SET_NULL, blank=True, null=True)
total = models.DecimalField(max_digits=18, decimal_places=9)
order_date = models.DateTimeField(null=True, blank=True)
added_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
def __str__(self):
return "%s" % self.order_number
views.py
from django.shortcuts import render
# Create your views here.
from django.views.generic import ListView
from mailer.models import Company, Contact, Order
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company
paginate_by = 100
The html
<div class="container">
<table class="table table-borderless">
{% if is_paginated %}
<tr><td>
{% if page_obj.has_previous %}
«
{% endif %}
</td>
<td></td>
<td></td>
<td>
{% if page_obj.has_next %}
»
{% endif %}
</td>
</tr>
{% endif %}
<tr>
<th>Name</th>
<th>Order Count</th>
<th>Order Sum</th>
<th>Select</th>
</tr>
{% for company in company_list %}
<tr>
<td>{{ company.name }}</td>
<td>{{ company.get_order_count }}</td>
<td>{{ company.get_order_sum|floatformat:2 }}</td>
<td><input type="checkbox" name="select{{company.pk}}" id=""></td>
</tr>
{% for contact in company.contacts.all %}
<tr>
<td> </td>
<td>{{ contact.first_name }} {{ contact.last_name }}</td>
<td>Orders: {{ contact.get_order_count }}</td>
<td></td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>
Is there any way in which I can reduce the initial load time. Please show me an efficient way to solve this problem.
Each {{company.get_order_count}} will hit the DB. Admittedly with a very simple query, but even so, it will slow things down.
You want to annotate the objects with this count. Use
from django.db.models import Count
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company
paginate_by = 100
def get_queryset(self):
return super().get_queryset().annotate( num_orders=Count('orders') )
and replace {{ company.get_order_count }} with {{ company.num_orders }}. This will turn N+1 DB queries into one DB query.
That's the easy one. There's a similar problem with get_order_sum which can almost certainly be solved with another annotation involving the django.db.Sum. Sorry but its late and my stomach is growling and I don't have any confidence that I would get that one right straight off the top of my head.
The cheat sheet on annotation is here. You might also need to look at aggregation.
Oh, and install Django_debug-toolbar in your developer environment. Every time in future it gets slow, you can just click there to see what SQL was executed and how long it took.

Display Django Foreign key on webpage

I have three models.
class Supplier(models.Model):
name = models.CharField(max_length=200, null=True)
class Order(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
class Product(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, null=True, blank=True)
on_order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True, blank=True)
I can display a table of all the products of a given order. However, I cannot seem to render the name of that supplier on the html page like <h4> Supplier: {{order.supplier}}</h4>
this is the view:
def PurchaseOrder(request, pk_order):
orders = Order.objects.get(id=pk_order)
products = Product.objects.filter(
on_order_id=pk_order).prefetch_related('on_order')
total_products = products.count()
supplier = Product.objects.filter(on_order_id=pk_order).prefetch_related('on_order')
context = {
'supplier': supplier,
'products': products,
'orders': orders,
'total_products': total_products, }
return render(request, 'crmapp/purchase_order.html', context)
here is my template:
{% extends 'crmapp/base.html' %}
{% load static %}
{% block content %}
<div class='main-site>'>
<h4> Supplier: {order.supplier}}</h4> **<----Does not work**
<h5>Order Number: {{order.id}}</h5> **<----Does not work**
<h5>Created on: {{order.date_created | date:"d/m/Y"}}</h5> **<----Does not work**
<h6>Total Items on Order: {{total_products}}</h6>
<input type="search" placeholder="Search any field..." class="form-control search-input" data-table="customers-list"/>
<table class="table table js-sort-table mt32 customers-list" id='myTable'>
<thead class="table" >
<tr>
<th class='header' onclick="sortTable(0)" scope="col">ID</th>
<th class='header' onclick="sortTable(1)" scope="col">Description</th>
<th class='header' onclick="sortTable(2)" scope="col">Cost</th>
<th class='header' onclick="sortTable(3)" scope="col">Order Quantity</th>
</tr>
</thead>
<tbody>
<tr>
{% for product in products %}
<td> {{product.id}}</td>
<td><h6><strong>{{product.description}}</strong></h6></td>
<td>£{{product.costprice |floatformat:2}}</td>
<td>{{product.on_order_quantity |floatformat:0}}</td>
</tr>
</tbody>
{% endfor %}
{% endblock %}
I've tried so hard... and didn't get very far.
Please help...
in context you write "orders", but in template you ask for "order", which is not defined. Try
<h4> Supplier: {{orders.supplier}}</h4>

Print a project name in jinja template

I have the following models
AcsObject class
class AcsObjects(models.Model):
object_id = models.IntegerField(primary_key=True)
object_type = models.ForeignKey('AcsObjectTypes', db_column='object_type')
context = models.ForeignKey('self', blank=True, null=True)
security_inherit_p = models.BooleanField()
creation_user = models.IntegerField(blank=True, null=True)
Projects class
class ImProjects(models.Model):
project = models.ForeignKey('AcsObjects',related_name='project', on_delete=False, primary_key=True)
project_name = models.CharField(max_length=1000)
project_nr = models.CharField(max_length=100)
project_path = models.CharField(max_length=100)
TimesheetTasks class
class TimesheetTasks(models.Model):
task = models.ForeignKey('Projects', related_name='t_task', on_delete=False, primary_key=True)
uom = models.ForeignKey('Categories', related_name='u_uom', on_delete=False)
planned_units = models.FloatField(blank=True, null=True)
billable_units = models.FloatField(blank=True, null=True)
I wrote the following code into views.py file.
class TimesheetData(TemplateView):
template_name = 'timesheet.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["da"] = TimesheetTasks.objects.all()
return context
I want to print a project_name but it is giving me a task_id ( task_id and project_id are same) using jinja template.
timesheet.html
<body>
<p> {{da}} </p>
<table class="table table-light">
<thead class="thead-light">
<tr>
<th>Task </th>
</tr>
</thead>
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
It is giving me a blank output
Output
That's simply just because you're not access to product_name field yet.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
With this, Jinja just render the task id (project id), because Jinja think that you're not need any other information but just the foreign key value. So to be able to see the project_name, you should use this instead: timesheet.task.project_name, it does the job.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task.project_name}} </td>
</tr>
{% endfor %}
</tbody>
Just want to mention that this could lead to another issue (performance issue) when Jinja have to query the data when render the template. To get rid of that, consider to use select_related which is an API of Django Queryset, check it out and gain some experiment that API, it really useful when using Django.

Right number of rows, but they're empty

I'm trying to display some tables, but they come up empty. The part that gets me is the number of rows is correct, but they are completely blank. If the table has 9 entries, I get 9 empty rows.
The same code is working for a different table
tables.py:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
views.py:
class ReportsView(LoginRequiredMixin, TemplateView):
template_name = 'reports.html'
def get_context_data(self, **kwargs):
context = super(ReportsView, self).get_context_data(**kwargs)
vouchers = VouchersTable(Vouchers.objects.all())
RequestConfig(self.request, paginate=False).configure(vouchers)
context['vouchers'] = vouchers
return context
reports.html:
{% extends "base.html" %}
{% load render_table from django_tables2 %}
{% block content %}
{% render_table vouchers %}
{% endblock content %}
models.py:
class Vouchers(models.Model):
creator_uid = models.IntegerField()
user_id = models.IntegerField()
username = models.CharField(max_length=255)
user_email = models.CharField(max_length=100)
event_name = models.CharField(max_length=255)
event_code = models.IntegerField()
valid_start = models.IntegerField()
valid_end = models.IntegerField()
redeemed = models.IntegerField()
redeem_date = models.IntegerField()
lab_version = models.CharField(max_length=40)
lab_model = models.IntegerField()
lab_id = models.IntegerField()
lab_duration = models.IntegerField()
resulting html (empty lines removed):
<div class="table-container">
<table>
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
</tbody>
</table>
</div>
Oh well...
You've declared the table like this:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
The correct way to write it is class Meta (Meta with a capital M): https://github.com/jieter/django-tables2

Django: template forloop multiple dictionaries

I need to load the the price of a liquor associated with the store, along wit the other data in the general liquor database. I know how to load the data in, and how to display in the info in two different tables, but I need that store price to simply be another row in the existing table, and I'm not sure how to do that. Here is the view:
def store(request, store_id=1):
a = Store.objects.get(StoreID=store_id)
b = StoreLiquor.objects.filter(storeID__exact=a).values_list('liquorID', flat=True)
x = StoreLiquor.objects.filter(storeID_exact=a)
args = {}
args['liquors'] = Liquor.objects.filter(id__in=b)
args['prices'] = x
args['a'] = a
return render(request, 'store.html', args)
Here is the html:
<pre>
<code>
{% if liquors.count > 0 %}
<table class="sortable">
<thead>
<tr>
<th scope="col">Liquor Code</th>
<th scope="col">Brand Name</th>
<th scope="col">Vendor Name</th>
</tr>
</thead>
<tbody>
{% for liquor in liquors %}
<tr>
<td>{{ liquor.LiquorCode }}</td>
<td>{{ liquor.BrandName }}</td>
<td>{{ liquor.VendorName }}</td>
<td>{{ liquor.StorePrice }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>None to show!</p>
{% endif %}
</code>
</pre>
Models:
class StoreLiquor(models.Model):
StoreLiquorID = models.AutoField(primary_key=True)
liquorID = models.ForeignKey(Liquor)
storeID = models.ForeignKey(Store)
StorePrice = models.DecimalField('Store Price', max_digits=5, decimal_places=2)
class Liquor(models.Model):
LiquorCode = models.PositiveSmallIntegerField('Liquor Code', max_length=5)
BrandName = models.CharField('Brand Name', max_length=32)
ADANumber = models.PositiveSmallIntegerField('ADA Number', max_length=3)
ADAName = models.CharField('ADA Name', max_length=25)
VendorName = models.CharField('Vendor Name', max_length=25)
LiquorType = models.CharField('ADA Name', max_length=20)
Proof = models.DecimalField(max_digits=3, decimal_places=1)
BottleSize = models.CharField('Bottle Size', max_length=7)
PackSize = models.PositiveSmallIntegerField('PackSize', max_length=3)
OnPremisePrice = models.DecimalField('On Premise Price', max_digits=5, decimal_places=2)
OffPremisePrice = models.DecimalField('Off Premise Price', max_digits=5, decimal_places=2)
ShelfPrice = models.DecimalField('Shelf Price', max_digits=5, decimal_places=2)
GlobalTradeItemNumber1 = models.BigIntegerField('Global Trade Item Number 1', max_length=14)
GlobalTradeItemNumber2 = models.BigIntegerField('Global Trade Item Number 2', max_length=14)
class Store(models.Model):
StoreID = models.AutoField(primary_key=True)
How about something like this:
View:
def store(request, store_id=1):
store = Store.objects.get(StoreID=store_id)
args = {}
args['store'] = store
return render(request, 'store.html', args)
Template:
<pre>
<code>
{% if store.storeliquor_set.count %}
<table class="sortable">
<thead>
<tr>
<th scope="col">Liquor Code</th>
<th scope="col">Brand Name</th>
<th scope="col">Vendor Name</th>
</tr>
</thead>
<tbody>
{% for storeliquor in store.storeliquor_set.all %}
<tr>
<td>{{ storeliquor.liquorID.LiquorCode }}</td>
<td>{{ liquor.liquorID.BrandName }}</td>
<td>{{ storeliquor.liquorID.VendorName }}</td>
<td>{{ storeliquor.StorePrice }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>None to show!</p>
{% endif %}
</code>
</pre>
Although I would recommend you to change your model to something like this (according to the python style guide):
class StoreLiquor(models.Model):
liquor = models.ForeignKey(Liquor)
store = models.ForeignKey(Store)
price = models.DecimalField('Store Price', max_digits=5, decimal_places=2)
class Liquor(models.Model):
liquor_code = models._positiveSmallIntegerField('Liquor Code', max_length =5)
brand_name = models.CharField('Brand Name', max_length =32)
ada_number = models._positiveSmallIntegerField('ADA Number', max_length =3)
ada_name = models.CharField('ADA Name', max_length =25)
vendor_name = models.CharField('Vendor Name', max_length =25)
liquor_type = models.CharField('ADA Name', max_length =20)
proof = models.DecimalField(max_digits =3, decimal_places =1)
bottle_size = models.CharField('Bottle Size', max_length =7)
pack_size = models._positiveSmallIntegerField('PackSize', max_length =3)
on_premise_price = models.DecimalField('On Premise Price', max_digits =5, decimal_places =2)
off_premise_price = models.DecimalField('Off Premise Price', max_digits =5, decimal_places =2)
shelf_price = models.DecimalField('Shelf Price', max_digits =5, decimal_places =2)
global_trade_item_number_1 = models.BigIntegerField('Global Trade Item Number 1', max_length =14)
global_trade_item_number_2 = models.BigIntegerField('Global Trade Item Number 2', max_length =14)
class Store(models.Model):
pass