I have gathered data from two tables that is Orders and Purchases (joined) and saved that in dictionary, when I'm printing the qty on the console its giving me the value but when I'm trying to print the values on template it not showing up however columns from the orders table like first name last name status address is shown on the template but qty and product from the purchases table is not showing up on the template but can be easily printed on console
can somebody help???
Models.py
Dispatcher = models.ForeignKey(Dispatchers , null=True, on_delete=models.SET_NULL )
Firstname = models.CharField(max_length=200 , null=True)
Lastname = models.CharField(max_length=200 , null=True)
Email = models.CharField(max_length=200 , null=True)
Address = models.CharField(max_length=200 , null=True)
Country = models.CharField(max_length=200 , null=True)
State = models.CharField(max_length=200 , null=True)
status = models.CharField(max_length=200 , null=True)
def __str__(self):
return self.Lastname
class purchases(models.Model):
orders_id = models.ForeignKey(Orders , null=True, on_delete=models.SET_NULL )
product = models.CharField(max_length=200 , null=True)
qty = models.CharField(max_length=200 , null=True)
price = models.CharField(max_length=200 , null=True)
def __str__(self):
return self.product
views.py file
dispatcherOrders = {}
orders = request.user.dispatchers.orders_set.all()
for order in orders:
dispatcherOrders[order] = purchases.objects.get(orders_id = order.id)
print(dispatcherOrders[order].qty)
return render(request , 'dispatcherOrders.html',{'dispatcherOrders' : dispatcherOrders})
dispatcherOrders.html
{%for Orders in dispatcherOrders%}
<tr>
<th scope="row">1</th>
<td>{{Orders.Firstname}}</td>
<td>{{Orders.Lastname}}</td>
<td>{{Orders.Address}}</td>
<td>{{Orders.product}}</td>
<td>{{Orders.qty}}</td>
<td>{{Orders.status}}</td>
</tr>
{% endfor %}
In your code, dispatcherOrders dictionary keys are orders and dictionary values are purchases:
dispatcherOrders[order] = purchases.objects.get(orders_id = order.id)
yet you are iterating only on dictionary keys, the orders:
{%for Orders in dispatcherOrders%}
To get the info from purchases, iterate the dictionary items too.
So your template code should be similar to
{%for Orders, Purchase in dispatcherOrders.items %}
<tr>
<th scope="row">1</th>
<td>{{Orders.Firstname}}</td>
<td>{{Orders.Lastname}}</td>
<td>{{Orders.Address}}</td>
<td>{{Purchase.product}}</td>
<td>{{Purchase.qty}}</td>
<td>{{Purchase.status}}</td>
</tr>
{% endfor %}
Here's how .items work: https://stackoverflow.com/a/6285769/3694363
Related
I am working on a Django project with 2 Models; Customer and Deposit and I want to display a list of Customers with their names, deposited dated, account number, and Total Deposited within the year so how do I do it the right way.
See what I have tried but Couldn't get the Customers' name in my Django Templates.
Models:
class Customer(models.Model):
surname = models.CharField(max_length=10, null=True)
othernames = models.CharField(max_length=20, null=True)
account_number = models.CharField(max_length=10, null=True)
address = models.CharField(max_length=50, null=True)
phone = models.CharField(max_length=11, null=True)
date = models.DateTimeField(auto_now_add=True, null=True)
#Get the url path of the view
def get_absolute_url(self):
return reverse('customer_create', args=[self.id])
#Making Sure Django Display the name of our Models as it is without Pluralizing
class Meta:
verbose_name_plural = 'Customer'
#
def __str__(self):
return f'{self.surname} {self.othernames} - {self.account_number}'
class Deposit(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True)
acct = models.CharField(max_length=6, null=True)
staff = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
deposit_amount = models.PositiveIntegerField(null=True)
date = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse('create_account', args=[self.id])
def __str__(self):
return f'{self.customer} Deposited {self.deposit_amount} by {self.staff.username}'
here is my view code:
def customer_list(request):
#Get Current Date
current_date = datetime.now().date()
#Get Current Month Name from Calendar
current_month_name = calendar.month_name[date.today().month]
group_deposits = Deposit.objects.filter(date__year=current_date.year).order_by('acct')
grouped_customer_deposit = group_deposits.values('acct').annotate(total `=Sum('deposit_amount')).order_by()`
context = { 'customers':grouped_customer_deposit,}
Here is how I tried to display the result in Django Template:
{% for deposit in customers %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ deposit.acct }}</td>
<td>{{ deposit.customer.surname }}</td>
<td>{{ deposit.total }}</td>
<td>{{ customer.deposit.date }}</td>
<th scope="row"><a class="btn btn-info btn-sm" href=" ">Deposit</a></th>
</tr>
{% endfor %}
Someone should graciously help with the most efficient way of getting the Total Deposit for each customer with their names, account number, and date deposited. Thank in anticipation for your kind answers.
As you are using the values method:
grouped_customer_deposit = group_deposits.values('acct').annotate(total `=Sum('deposit_amount')).order_by()`
Django will return a queryset that returns dictionaries rather than model instances. See Django Queryset API reference for more details.
This means that you cannot reference your model relationships as you are trying to do here:
<td>{{ deposit.customer.surname }}</td>
as that information will not be in the dictionary passed to the template (you can do a print of grouped_customer_deposit in your view, or display it in your template -- {{ customers }} -- to see what I mean).
Ergo, if you remove your call to values() then your template will receive model instances which should solve your problem, and make your template work as-is.
grouped_customer_deposit = group_deposits.annotate(total `=Sum('deposit_amount')).order_by()`
(Although your syntax for your annotate is not correct, so I'm assuming that was a mistake when you pasted your code here.)
I'm working on an ecommerce app, and I have a template that displays all my products.
I want to show how many of the item are in the cart. But I can't seem to figure out how to get that information from my for loop.
I want to check if the current product in my for loop matches with an OrderItem for that user.
I'm able to do this in the detail view but not my catalogue/index
Code:
template
{% for product in products %}
{{product.title}} - {{product.quantity_in_cart}}
{% endfor %}
(As of right now, product.quantity_in_cart does nothing. I would like it to show how many of this product are in the cart)
view
def product_index(request):
title = "My Products"
products = Product.objects.all()
order = get_cart(request)
cart = Order.objects.get(id=order.id, complete=False)
items = cart.orderitem_set.all()
context = {
'title' : title,
'products' : products,
'cart' : cart,
'items': items
}
return render(request, "store/product_index.html", context)
models
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
complete = models.BooleanField(default=False, null=True, blank=False)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
class Product(models.Model):
name = models.CharField(max_length=64)
slug = models.SlugField(unique=True, null=True)
description = RichTextField(blank=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
quantity = models.IntegerField()
def product_index(request):
title = "My Products"
products = Product.objects.all()
order = get_cart(request)
cart = Order.objects.get(id=order.id, complete=False)
items = cart.orderitem_set.all()
# Changes
for product in products:
qty = 0
if items.filter(product=product).exists():
qty = items.get(product=product).quantity
setattr(product, 'quantity_in_cart', qty)
context = {
'title' : title,
'products' : products,
'cart' : cart,
'items': items
}
return render(request, "store/product_index.html", context)
Add a session key called 'cart' which can be a list and each item in the list can be a dictionary containing 'name', 'quatity' and price, as the the user is adding to the cart you add you the session variable and in the template you can render the cart using a for like this
{% for product in request.session.carr%}
{%endfor%}
I am struggling to get current remaining stock in my inventory application.
I have written code to calculate remaining quantity but it calculates based on purchased quantity only. I want to add total sold quantity and find the difference between purchased and total sold quantity.
How do I calculate total sold quantity and calculate the remaining stock.
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=100)
slug = models.CharField(max_length=100)
price = models.DecimalField(max_digits=6, decimal_places=2)
quantity = models.IntegerField(null=True, blank=True)
category = models.ForeignKey(
Category, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.name
class Stock(models.Model):
sold_quantity = models.IntegerField(null=True, blank=True, default=0)
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.product.name
#property
def get_difference(self):
total = self.product.quantity-self.sold_quantity
return total
Views.py
def add_sales(request):
form = AddSalesForm()
if request.method == 'POST':
form = AddSalesForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.product.quantity -= instance.sold_quantity
instance.save()
return redirect('stock_details')
contex = {'form': form}
return render(request, 'stockmgmt/add_sales.html', contex)
templates
{% extends 'stockmgmt/base.html' %}
{% block content %}
<form method="GET">
Add Sales
<p>
<table class="table table-bordered">
<tr>
<th>Item</th>
<th>Category</th>
<th>Purchased Qty</th>
<th>Sold Qty</th>
<th>Remaining Qty</th>
<th>Price</th>
<th>Action</th>
</tr>
{% for item in stocks %}
<tr>
<td>{{item.product.name}}</td>
<td>{{item.product.category}}</td>
<td>{{item.product.quantity}}</td>
<td>{{item.sold_quantity}}</td>
<td>{{item.get_difference}}</td>
<td>{{item.product.price}}</td>
<td>Delete
Edit
</td>
</tr>
{% endfor %}
</table>
</form>
{% endblock %}
you need to update the existing stock after each order
for ex.
opening stock = 100
current stock = 100
after first order of 10 qty
opening stock = 100
current stock = current stock - order qty = 100 - 10 = 90
after second order of 5 qty
opening stock = 100
current stock = current stock - order qty = 90 - 5 = 85
if i purchase or add new stock the current stock will be updated
after adding 50 qty
current stock = current stock + purchase qty = 85 + 50 = 135
you can have a log table (Model) for income and outgoing of stock for tracking
hope you understand the concept i'm trying to explain
I'm trying to display data from my template. The issue I'm having is with the foreign key in the BattingStats table that references playerid of the PlayerInfo table. When I get it to display, the data for that field is showing but it is wrapped in parenthesis and preceded by ReferencedTable object. So for me it looks like this PlayerInfo object (smithjo05). Why would it be doing that and how would i get it to just show the playerid? Help is appreicated. Thanks.
VIEWS
def battingview(request):
playerinfo = PlayerInfo.objects.all()
playerstats = BattingStats.objects.filter(year=2018)
return render(request, 'playerstats/battingRegStnrd2018.html', {'playerinfo':playerinfo,'playerstats': playerstats})
MODELS
class BattingStats(models.Model):
id = models.IntegerField(db_column='ID', primary_key=True)
playerid = models.ForeignKey('PlayerInfo', models.DO_NOTHING, db_column='playerID', blank=True, null=True)
player = models.CharField(db_column='Player', max_length=255, blank=True, null=True)
hr = models.IntegerField(db_column='HR', blank=True, null=True)
rbi = models.IntegerField(db_column='RBI', blank=True, null=True)
ba = models.FloatField(db_column='BA', blank=True, null=True)
class PlayerInfo(models.Model):
playerid = models.CharField(db_column='playerID', primary_key=True, max_length=255)
namefirst = models.CharField(db_column='nameFirst', max_length=255, blank=True, null=True)
namelast = models.CharField(db_column='nameLast', max_length=255, blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
debut = models.CharField(max_length=255, blank=True, null=True)
finalgame = models.CharField(db_column='finalGame', max_length=255, blank=True, null=True)
HTML
{% for index in playerstats %}
<td>{{ index.playerid }}</td>
<td>{{ index.year}}</td>
<td>{{ index.age}}</td>
<td>{{ index.team}}</td>
<td>{{ index.league}}</td>
{% endfor %}
{% for index in playerstats %}
{{ index.playerid }}
{% endfor %}
Browser
PlayerInfo object (smithjo05)
PlayerInfo object (cruzne02)
PlayerInfo object (jonesad01)
You just need to add __str__ method to your PlayerInfo model:
class PlayerInfo(models.Model):
playerid = models.CharField(db_column='playerID', primary_key=True, max_length=255)
namefirst = models.CharField(db_column='nameFirst', max_length=255, blank=True, null=True)
namelast = models.CharField(db_column='nameLast', max_length=255, blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
debut = models.CharField(max_length=255, blank=True, null=True)
finalgame = models.CharField(db_column='finalGame', max_length=255, blank=True, null=True)
def __str__(self):
return self.playerid
This allows to change default representation of instance when you convert it to string, for example in templates.
Im trying to join two tables together before being sent to a view, using _set in a view causes 100s of queries which is highly inefficient.
example structure sites.models.py
class SiteData(models.Model):
location = models.CharField(max_length=50)
site_type = models.ForeignKey(SiteTypes, verbose_name="Site Type", \
on_delete=models.PROTECT)
bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
opening_date = models.DateField(verbose_name="Site opening date")
last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh", \
blank=True, null=True)
is_live = models.BooleanField(default=False, verbose_name="Is this a live site?")
example structure config.models.py
class SiteSubnets(models.Model):
site_data = models.ForeignKey(SiteData, verbose_name="Location", \
on_delete=models.PROTECT, blank=True, null=True)
subnet = models.GenericIPAddressField(protocol='IPv4', \
verbose_name="Subnet", blank=True, null=True)
subnet_type = models.ForeignKey(SubnetTypes, verbose_name="Subnet Type")
vlan_id = models.IntegerField(verbose_name="Vlan ID", blank=True, null=True)
peer_desc = models.IntegerField(verbose_name="Peer description", blank=True, null=True)
site_ip = models.BooleanField(default=False, verbose_name="Is this a site supernet IP?")
class Meta:
verbose_name = "Site Subnets"
verbose_name_plural = "Site Subnets"
Queries:
site_subnets = SiteSubnets.objects.only('subnet').filter(site_ip=True)
site_data = SiteData.objects.only('location','is_live','bgp_as','postcode','opening_date','live_link_type')
Desired Outcome example:
Location | Subnet | BGP AS
---------------------------------
London | 10.10.10.0 | 65001
Manchester | 10.10.20.0 | 65002
...
I cant do a select_related without having the SitesSubnet table as the main table, as when I do it on site data, I get
django.core.exceptions.FieldError: Invalid field name(s) given in select_related: 'site_subnets'. Choices are: site_type
If I use the SiteSubnet as the main table, if a Site does not have a SiteSubnet.site_up I wont get the Site info. displayed
does anyone know a way around this that will display all the data and not run n+1 queries?
EDIT:
prefetch also fails with the below error:
AttributeError: Cannot find 'site_subnets_set' on SiteData object, 'site_subnets_set' is an invalid parameter to prefetch_related()
I would be sending the data to a template to be accessed in a loop i.e
<table>
<tr>
<td>Location</td>
<td>Subnet</td>
<td>BGP AS</td>
<tr>
{%for site in sitedata %}
<tr>
<td>{{ site.location }}</td>
<td>{{ site.subnet }}</td>
<td>{{ site.bg_as }}</td>
<tr>
{% endfor %}
Thanks
You can use prefetch_related to prefetch sitesubnets for the sitedata queryset.
SiteData.objects.prefetch_related('sitesubnets_set')