Regrouping in Django Template With Grouping in views - django

I have a model with different forginekey wish I could like to group it by student. I was successfully done that but in my template, I want to nested the result or regroup it by subject according to students.
model.py
class Result(models.Model):
examtype = models.ForeignKey(ExamType, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
subject = models.ForeignKey(SubjectAppointment, on_delete=models.CASCADE)
test = models.FloatField()
exam = models.FloatField()
total = models.FloatField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def save(self, *args, **kwargs):
self.total = self.test + self.exam
super().save(*args, **kwargs)
def __str__(self):
return self.student.matricnumber
def get_result_total(self):
return int(float(f'{self.test + self.exam}'))
views.py
def ReportView(request):
template_name = 'teacher/report.html'
score = Result.objects.values('student', 'exam', 'test', 'subject__subject__name').annotate(student_totalscore=Sum('total')).annotate(attending=Count('subject'))
print(score)
context = {
'score': score,
}
return render(request, template_name, context)
report.html
{% for s in score %}
{% regroup score by s.student as student_list %}
{% for a in student_list %}
<!-- {% for b in a.list %} -->
<tr>
<td>{{ b.subject__subject__name }}</td>
<td>{{ b.test }}</td>
<td>{{ b.exam }}</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<!-- {% endfor %} -->
{% endfor %}
{% endfor %}

Related

How to use query result in if statement tag in Django template

Is it possible to use query result in if statement template tag
category.html (template):
{% for ETF in ETFs %}
<td>{{ ETF.ticker }}</td>
<td>{{ ETF.full_name }}
{% if ETF.asset_class == "Inverse" %} <! –– this don't work ––>
<span class="alert-warning" > Inverse </span>
{% endif %} </td>
{% endfor %}
views.py
def etf_list(request):
filtered_results = ETF.objects.all()
return render(request, "etf/category.html", {
"ETFs": filtered_results,
})
It does not work here because ETF.asset_class is not a string object. So it cant equal to another string. Is there other ways to make it work? I have a table of items in the html and want to highlight some items that have some model attributes.
models.py
class ETF(models.Model):
ticker = models.CharField(max_length=6, blank=False, db_index=True, unique=True, primary_key=True)
asset_class = models.ForeignKey(Asset_class, on_delete=models.PROTECT, blank=True)
class Asset_class_style(models.Model):
name = models.CharField(max_length=50, blank=False, unique=True)
details = models.CharField(max_length=500, blank=True)
slug = models.SlugField(default="", null=False, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super().save(*args, **kwargs)
You cannot compare asset_class with string, but you can compare name attribute which is string. So:
{% for ETF in ETFs %}
<td>{{ ETF.ticker }}</td>
<td>{{ ETF.full_name }}
{% if ETF.asset_class.name == "Inverse" %} <! –– name attribute of assest_class ––>
<span class="alert-warning" > Inverse </span>
{% endif %} </td>
{% endfor %}

Django, How to display 2 models on a Listview

I am working with my first Django project
**model.py**
class product(models.Model):
product_code = models.CharField(max_length=15, unique=True)
product_name = models.CharField(max_length=100)
class stock_product(models.Model):
product_code = models.CharField(max_length=15)
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
**views.py**
class productList(ListView):
model = product
template_name = 'product/product_list.html'
def get_queryset(self):
queryset = super(productList, self).get_queryset()
self.filterset = productFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = self.filterset
return context
**product_list.html**
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.price }}</td>
<td>{{ alist.quantity }}</td>
</tr>
{% endfor %}
Sample Data in tables
**product**
['11111','paper'
'22222','Wood']
**stock_product**
['11111','BR1',150, 10
'11111','BR2',120, 10
'11111','BR3',100, 15
'22222','BR1',50, 200
'22222','BR2',70, 200
'22222','BR3',40, 250]
I want to get price and quantity from stock_product model, we can change branch_code by user
how can we do Plese help.
Thanks, But I want display only user branch (if user branch 'BR1' display only 'BR1')
**views.py**
class productList(ListView):
model = product
template_name = 'product/product_list.html'
def get_queryset(self):
queryset = super(productList, self).get_queryset()
self.filterset = productFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
stock = stock_product.objects.all(). # this line added
context['filter'] = self.filterset
context['stock'] = stock # this line added
return context
Now having this you can access the stock from your template:
**product_list.html**
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.price }}</td>
<td>{{ alist.quantity }}</td>
</tr>
{% endfor %}
{% for s in stock %}
<tr>
<td>{{ s.product_code }}</td>
<td>{{ s.product_branch }}</td>
</tr>
{% endfor %}
BUT I have to just do not recommend you do this. Why? well, I suppose you want to make the match of the product_code. Except of that you should use ForeignKey on the models and so you will have a much simple code and logic:
Model:
class stock_product(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE) # this
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
And so now without modifying your view you could do this on the template to access the data:
template:
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.stock_product.branch_code }}</td>
<td>{{ alist.stock_product.quantity }}</td>
<td>{{ alist.stock_product.price }}</td>
</tr>
{% endfor %}
how about change the model with using foreign keys.
and use the django_tables2.
# **model.py**
from django.db import models
class product(models.Model):
product_code = models.CharField(max_length=15, unique=True)
product_name = models.CharField(max_length=100)
class stock_product(models.Model):
# product_code = models.CharField(max_length=15)
product = models.ForeignKey(product, on_delete=models.CASCADE)
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
this is table code for django_tables2.
class DetailedDataTable(tables.Table):
product_code = tables.Column(verbose_name='product_code', accessor='product_id')
product_name = tables.Column(verbose_name='product_name', accessor='product_id')
class Meta:
model = stock_product
template_name = "django_tables2/bootstrap.html"
fields = ('product_code', 'product_name', 'branch_code', 'quantity', 'price')
def render_product_code(self,value, record):
return product.objects.get(id=value).product_code
def render_product_name(self,value, record):
return product.objects.get(id=value).product_name
and this is view
def view(request):
template_name = 'template.html'
query_set = stock_product.objects.all()
table = DetailedDataTable(qs)
context={
'table':table,
}
return render(request, template_name, context)
and this is for template page uses.
{# tutorial/templates/tutorial/people.html #}
{% load render_table from django_tables2 %}
<!doctype html>
<html>
<head>
<title>List</title>
</head>
<body>
{% render_table table %}
</body>
</html>
:)

Display number of views for a specific post for specific user in a table using django

i want to display number of views in a table for a specific post. I already have the data stored in db. it seems that print statement print('count', context['count_view']) is working inside get_context_data method but it is not working as expected in the template. Don't worry about the data inside the image, its actually dummy data. Anyone helpenter image description here
models.py
class ObjectViewed(models.Model):
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
ip_address = models.CharField(max_length=220, blank=True, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # User, Blog, or any other models
object_id = models.PositiveIntegerField() # User id, Blog id, or any other models id
content_object = GenericForeignKey('content_type', 'object_id')
timestamp = models.DateTimeField(auto_now_add=True)
views.py
class PostListView(ListView):
model = Post
template_name = 'edmin/post/postList.html'
context_object_name = 'posts'
ordering_by = ['-created']
def get_queryset(self):
post=Post.objects.filter(author=self.request.user)
return post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
post=Post.objects.filter(author=self.request.user)
c_type = ContentType.objects.get_for_model(Post)
for p in post:
context['count_view'] = ObjectViewed.objects.filter(content_type=c_type, object_id=p.id).count()
print('count',context['count_view'])
return context
postList.html
{% for post in posts %}
{% if post.status == 'Draft' %}
{% else %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><a style="color:blue" href="{% url 'edmin:post_detail_view' pk=post.pk %}">{{ post.title }}</a></td>
<td>{{ post.banner_title }}</td>
<td>{{ post.created }}</td>
<td>{{ count_view }}</td>
<td>{{ post.status }}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% endif %}
{% endfor %}
Since context allows 'dict', you can pass all of your views through context.

Django: Two questions on extending ListView with get_context_data

I tried something similar to this. I have three models:
class PartBase(models.Model):
name = models.CharField('Name', max_length=120)
price = models.DecimalField("Price per part", decimal_places=2, max_digits=6)
class Sett(models.Model):
name = models.CharField('Name', max_length=120)
class PartRelation(models.Model):
part = models.ForeignKey(PartBase, on_delete=models.CASCADE)
qty = models.PositiveIntegerField("Quantity")
sett = models.ForeignKey(Sett, related_name='setts', on_delete=models.SET_NULL, null=True)
def get_position_price(self):
return self.qty * self.part.price
now I want to add the price of all the items in a Sett in a row in my HTML.
{% extends 'base.html' %}
{% block title %}
Add Set
{% endblock title %}
{% block content %}
<table class="table">
<tr>
<th>Set Name</th>
<th>Total price</th>
</tr>
{% for set in setts %}
<tr>
<td>{{ set.name }}</td>
<td>{{ set.test }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
I wanted to override the get_context_data method somehow like this:
class SetListView(ListView):
model = Sett
context_object_name = "setts"
def get_context_data(self,**kwargs):
context = super(SetListView, self).get_context_data(**kwargs)
context['test'] = "price"
return context
But I only get an empty field in the template (which I assumed would have the word "price".
I can access the price in the shell via
for s in Sett.objects.all():
pr = PartRelation.objects.filter(sett=s)
price = 0
for p in pr:
price += p.get_position_price()
But how would I put the code from the shell in the get_context_data() function, so that for every row I get the corresponding total price?
This did the trick:
class SetListView(ListView):
model = Sett
context_object_name = "setts"
def get_context_data(self, **kwargs):
context = super(SetListView, self).get_context_data(**kwargs)
for s in context["setts"]:
pr = PartRelation.objects.filter(sett=s)
s.total_price = 0
for p in pr:
s.total_price += p.get_position_price()
return context
I would gladly get feedback if that is a good approach (and why not/how to do better).

create a particular detail view

i need help to formulate a query.
my models are this:
class Rider(models.Model):
id_rider = models.IntegerField(default = 0,blank= True, primary_key=True)
first_name = models.CharField(max_length = 256,blank= True)
[...]
def str(self):
return self.display_name
class Risultato(models.Model):
TYPE_CHOICES = (('SR','sr'),('ITT', 'itt'),('HC', 'hc'),('1C','1c'),('TTT','ttt'))
id_rider = models.ForeignKey(Rider,related_name='rider', on_delete=models.CASCADE)
id_stage = models.ForeignKey(Stage,related_name='team', on_delete=models.CASCADE)
type_ris = models.CharField(choices=TYPE_CHOICES,max_length = 256,blank= True)
rank = models.IntegerField(default = 0,blank= True)
punti = models.IntegerField(default = 0,blank= True)
def __str__(self):
return self.id_raider,self.id_stage,self.rank
i need to create a Detail View to details of riders, somethings like this:
-------------------------------------------
Rider: [display_name]
age : [age]
...
...
--------SCORE HISTORY-----
stage sr/itt ttt hc 1c tot
1 100 null 10 0 110
2 null 20 5 10 35
Thanks in advance!!
UPDATE
i add the view and the template, but i can't see the table
view.py:
class RiderDetails(DetailView):
model = Rider
template_name = 'game/rider_detail.html'
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(**kwargs)
context_data['risultato_qs'] = Risultato.objects.filter(id_rider=self.object)
return context_data
rider_detail.html:
{% extends 'game/base.html'%}
{% block content %}
<h1>{{ rider.display_name }}</h1>
<table>
<tbody>
{% for risultato in risultato_qs %}
<tr>
<td>{{ risultato.stage }}</td>
<td>{{ risutato.type_ris }}</td>
<td>{{ risutato.punti }}</td>
... etc ...
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
screen page
A quick example might look like:
class RiderDetails(DetailView):
model = Rider
template_name = 'path_to_rider_template'
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(*args, **kwargs)
context_data['risultato_qs'] = Risultato.objects.filter(id_rider=self.object)
return context_data
Then in your template you can, for example:
... Rider details here ...
<table>
<tbody>
{% for risultato in risultato_qs %}
<tr>
<td>{{ risultato.stage }}</td>
<td>{{ risutato.type_ris }}</td>
... etc ...
</tr>
{% endfor %}
</tbody>
</table>