How to display sum of disctinct items in django? - django

I would like to display sum all the distinct categories of the products that belongs to the user. I searched on the web, but all the things that I tried doensn't work. You may find the models,view and template below. It doesn't give me anything at the html.
Model:
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,related_name='products')
category = models.CharField(max_length=120)
brand = models.CharField(max_length=120)
product = models.CharField(max_length=120)
price = models.DecimalField(decimal_places=2,max_digits=100)
class Comp_Product(models.Model):
product = models.ForeignKey(Product,on_delete=models.CASCADE, related_name="comp_products")
competitor = models.URLField()
price = models.DecimalField(decimal_places=2,max_digits=100)
change = models.FloatField()
stock = models.BooleanField()
last_update = models.DateField(auto_now_add=True)
View:
class DashboardList(ListView):
template_name='dashboard_by_user.html'
def get_queryset(self):
return Product.objects.filter(user=self.request.user).annotate(count_category=Count('category',distinct=True)).aggregate(sum_category=Sum('count_category'))
template:
{% for product in product_list %}
{{product.sum_category}}
{%endfor%}

welcome to stackoverflow,
I'm assuming that you want to count the number of distinct categories for the given user. This can be done like this:
views.py:
from django.views.generic.list import ListView
from .models import Product
class DashboardList(ListView):
template_name = 'dashboard_by_user.html'
def get_queryset(self):
return Product.objects.filter(user=self.request.user)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Products = context['object_list']
context['distinct_category_count'] = Products.values(
'category').distinct().count()
return context
dashboard_by_user.html:
<h1>Products</h1>
<ul>
{% for product in object_list %}
<li>{{ product.brand }} - {{ product.product }} - {{ product.category }}</li>
{% empty %}
<li>No Producs yet.</li>
{% endfor %}
</ul>
<p> Number of distinct categories: {{ distinct_category_count }} </p>
This should give you an output similar to this one:

Related

Cannot see foreign key values in the template

This is my 2nd week learning Django. I'm trying to get comfortable with Django Template Language. I'm trying to make an Inventory app with 4 models. The views for them are class-based.
The templates for Ingredient and Menu work as expected. However, I'm struggling with trying to loop through values from the Purchase model which has a foreign key field 'menu_item'. The template is not showing anything from the for loop. I've referred numerous articles here to find most of them use function-based views. I've tried using {% for purchase in purchase_set %}, {% for purchase in purchase_set.all %}. I know the object to iterate over is a query-set. I cannot figure out what to do?
MODELS.PY
from django.db import models
# Create your models here.
class Ingredient(models.Model):
Pounds = 'lbs'
Ounces = 'oz'
Grams = 'gms'
Eggs = 'eggs'
Piece = 'piece'
Litre = 'litre'
unit_choices = [(Pounds, 'lbs'),
(Ounces, 'ounces'),
(Grams, 'grams'),
(Eggs, 'eggs'),
(Piece, 'piece'),
(Litre, 'litre')]
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
unit_price = models.FloatField(default=0.0)
quantity = models.FloatField(default=0.0)
unit = models.CharField(max_length=10, choices=unit_choices)
class Meta:
ordering = ['id']
def __str__(self):
return self.name
class MenuItem(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=50)
price = models.FloatField(default=0.0)
class Meta:
ordering = ['id']
def __str__(self):
return self.title
class RecipeRequirement(models.Model):
menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
quantity = models.FloatField(default=0.0)
def __str__(self):
return self.menu_item.title
class Purchase(models.Model):
menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
timestamp = models.DateTimeField()
id = models.AutoField(primary_key=True)
class Meta:
ordering = ['id']
def __str__(self):
return self.menu_item.title
VIEWS.PY:
from django.shortcuts import render
from .models import Ingredient, MenuItem, RecipeRequirement, Purchase
from django.views.generic import ListView
def home(request):
return render(request, 'inventory/home.html')
class IngredientView(ListView):
model = Ingredient
template_name = 'inventory/ingredients.html'
class PurchaseView(ListView):
model = Purchase
template_name = 'inventory/purchases.html'
class MenuView(ListView):
model = MenuItem
template_name = 'inventory/menu.html'
PURCHASES.HTML
<h3>This is purchases page.</h3>
{% block content %}
<table>
{% for purchase in purchase_set.all %}
<tr>
<td>{{ purchase.title }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
The title field you are trying to show is in MenuItem model that is used as foreignkey in Purchase model with menu_item field. ListView class returns to context yours purchases in object_list key. So in Your purchases.html template:
<h3>This is purchases page.</h3>
{% block content %}
<table>
{% for purchase in object_list %}
<tr>
<td>{{ purchase.menu_item.title }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
PS. This `purchase_set' is referring to reverse relationship. So if you would want to show all purchases of MenuItem you would do:
{% for item in menuitems %}
<h1>{{ item }}</h1>
{% for purchase in item.purchase_set.all %}
<p>{{ purchase.timestamp }}</p>
{% endfor %}
{% endfor %}

Unable to display parent table with child table in a for loop with template tagging in Django

I want to display an unordered list of NBA teams from my teams table database. Within each team, I want an ordered list of players on that team. So basically I want to produce a list of all objects from my parent table and for each object from the parent table I want a list of all objects from the child table related the parent table. I understand that the problem is methods are not allowed in template tagging, so 'team.players_set.all()' would not be allowed. How else can I get the results that I want?
class Teams(models.Model):
name = models.CharField(max_length=20, unique=True)
num_of_plyrs = models.IntegerField()
def __str__(self):
return f"{self.name} have {self.num_of_plyrs} players."
class Meta:
verbose_name_plural = "Teams"
class Players(models.Model):
name = models.CharField(max_length=20)
team = models.ForeignKey(Teams, on_delete=models.CASCADE)
def __str__(self):
return f"{self.name} plays for {self.team}"
class Meta:
verbose_name_plural = 'Players'
__________________________________________________________________________________
def teams(request):
teams = Teams.objects.all()
context = {'teams': teams}
return render(request, 'one_app/teams.html', context)
__________________________________________________________________________________
<h3>NBA Teams</h3>
<ul>
{% for team in teams %}
<li>
<p>Team: {{ team.name }}</p>
<p>Number of players: {{ team.num_of_plyrs }}</p>
<ol>
{% for plyr in team.players_set.all() %}
<li>{{ plyr.name }}</li>
{% endfor %}
</ol>
</li>
{% empty %}
<li>There are no teams listed.</li>
{% endfor %}
</ul>
{% for player in team.players_set.all %}
table name should be singular
you can set related_name and use players instead players_set
team = models.ForeignKey(Teams, related_name='players',on_delete=models.CASCADE)
make use of select_related
One way to achieve this is:
class PlayersView(ListView):
model = Team
...
def get_queryset(self, **kwargs):
teams = []
queryset = super().get_queryset()
for team in queryset:
players = team.player_set.all()
for player in players:
teams.append([team, (player.name, ...)]
return teams
And in your template:
{% for team, players in teams %}
...
{% for player in players %}
...
{% endfor %}
{% endfor %}
ALTERNATIVE
If you know this is something you might be using a lot and to simplify your view, you can also create a manager:
from your_app.managers import TeamManager
class Team(models.Model):
...
objects = Manager()
team_manager = managers.TeamManager.as_manager()
...
In a file manager.py or anything you want:
from django.db.models import QuerySet
class TeamManager(QuerySet):
def table_queryset(self):
queryset = self.all()
teams = []
for team in queryset:
players = team.player_set.all()
for player in players:
teams.append([team, (player.name, ...)]
return teams
And then in your view:
class PlayersView(ListView):
model = Team
queryset = Team.player_manager.table_queryset()

How to get data from Django Many-Many relationship?

How to get all product for every order on Templates. Please help me
Model.py
class Order(models.Model):
customer_id= models.ForeignKey(Customers )
delivery_add_id= models.ForeignKey(DeliveryAddresses)
class OrderItem(models.Model):
order_id = models.ForeignKey(Order, related_name='orderId')
product_id = models.ForeignKey('Products', related_name='productId')
class Products(models.Model):
cat_id = models.ForeignKey('Categories')
name = models.CharField(max_length=200)
price = models.FloatField()
Templates
<tr>
<th>Product ordered</th>
<td>
<ul>
{% for prod in order.orderId.productId.product_set.all%}
<li>{{pro}}</li>
{% endfor %}
</ul>
{{order.orderId.productId.product_set.all}}
</td>
</tr>
https://i.stack.imgur.com/XJ3zG.png
Views.py
class productList(ListView):
model= Products
context_object_name = 'product_list'
def get_queryset(self):
return Products.objects.all()
class productDetail(DetailView):
context_object_name = 'product'
model = Products
queryset = Products.objects.all()
class orderList(ListView):
model = Order
context_object_name= 'order_list'
def get_queryset(self):
return Order.objects.all()
class orderDetail(DetailView):
context_object_name ='order'
model = Order
queryset= Order.objects.all()
This is the general relationship I have set up.I'm trying to do is, in a templates, i want to show all product for every order. Order-product : many to many relationship. Please help me
It should be like this:
{% for orderItem in order.orderId.all %}
{% for pro in orderItem.productId.all %}
<li>{{pro}}</li>
{% endfor %}
{% endfor %}

Accessing a attribute of another object through a model linked by ManyToMany

Here are my two models
class Category(models.Model):
name = models.CharField(max_length = 50)
description = models.CharField(max_length = 1000)
created = models.DateTimeField(auto_now_add=True)
def __unicode__(self, ):
return self.name
class Post(models.Model):
subject = models.CharField(max_length=50, blank=True)
description = models.CharField(max_length=1000)
created = models.DateTimeField(auto_now_add=True)
category = models.ManyToManyField(Category)
def __unicode__(self, ):
return self.subject
I'm displaying the subject, description, and date of each post in a template. But I also want to display the respective category for each post as well.
Here's the part of my view
def index(request):
posts = Post.objects.order_by("-created")
return render(request,'posts/index.html', {'posts':posts})
and then how I'm trying to display it in a template:
{% for post in posts %}
<div>
{{ post.subject }}<br />
{{ post.description }}<br />
{{ post.created }} | of {{ post.category }}
</div>
{% endfor %}
But the category will not show up, all I get is
<django.db.models.fields.related.ManyRelatedManager object at 0x7ff7e40a0c90>
I've tried doing post.category.name and other random combinations but it either gives nothing or a parsing error. I have no idea how to get the category displayed.
That's a Manager. Use it as you would any other Manager (e.g. Post.objects).
{% for category in post.category.all %}

Displaying a many-to-many fields

I seem to have a problem displaying work orders. in my app. The clients does not have the same problem so why does the work orders not show up. Actually it is as almost as a black space appears rather than text that should appear from my database.
The problem seems to be because work orders have a many-to-many field. If I have {{work_orders}}instead of say `{{work_orders.description}}, I get this
<django.db.models.fields.related.ManyRelatedManager object at 0xa042c6c>
Here are some output from my app.
#views
#login_required
def invoice_details(request, id=1):
invoices_list = Invoice.objects.filter(pk=id)
client = invoices_list[0].client
work_orders = invoices_list[0].work_orders
return render_to_response(('invoice_details.html', locals()), {'work_orders': work_orders,'client': client, 'invoices_list': invoices_list}, context_instance=RequestContext(request))
#models.py
class Invoice(models.Model):
client = models.ForeignKey(Client)
date = models.DateField()
invoice_no = models.CharField(max_length=16)
work_orders = models.ManyToManyField(Work_Order)
contract_info = models.ForeignKey(Contract_Info)
def __unicode__(self):
return self.invoice_no
#invoice_details.html
{{client.company}}<br/>
{{client.address}}<br/>
{{client.city}}<br/>
{{client.postcode}}<br/>
{{work_orders.description}}<br/>
{{work_orders.quantity}}<br/>
{{work_orders.item_no}}<br/>
should it not be work_orders.all, e.g.
{% for work_order in work_orders.all %}
{{work_order.description}}
{% endfor %}
#views
from django.shortcuts import get_object_or_404
#login_required
def invoice_details(request, id=1):
invoice = get_object_or_404(Invoice, pk=id)
return render_to_response(('invoice_details.html', locals()), {'invoice': invoice}, context_instance=RequestContext(request))
#models.py
class Invoice(models.Model):
client = models.ForeignKey(Client)
date = models.DateField()
invoice_no = models.CharField(max_length=16)
work_orders = models.ManyToManyField(Work_Order)
contract_info = models.ForeignKey(Contract_Info)
def __unicode__(self):
return self.invoice_no
#invoice_details.html
{{ invoice.client.company }}<br/>
{{ invoice.client.address }}<br/>
{{ invoice.client.city }}<br/>
{{ invoice.client.postcode }}<br/>
{% for work_order in invoice.work_orders.all %}
{{ work_order.description }}<br/>
{{ work_order.quantity }}<br/>
{{ work_order.item_no }}<br/>
{% endfor %}