How to show the values of intermediate m2m model in Django template - python

I am iterating through a queryset in the template using template tags to show the data of existing database entries (i.e. Product Details of each product in a customer order). However, I want to show users some values (i.e. quantity and price) that are located in an intermediate m2m model between the Product and Order models for each product in the order.
My approach was to create the querysets in views and pass them through context into the template but I cannot seem to 'call' the values at the template using template tags for the intermediate m2m data. Perhaps my context is passing the wrong queryset or my approach is just wrong.
My code is below and I am thankful for any help you can give:
Models.py Snippet
class Product(models.Model):
article_number = models.ForeignKey('Article_number')
color = models.ForeignKey('Color')
size = models.ForeignKey('Size')
barcode = models.ForeignKey('Barcode')
product_name = models.ForeignKey('Product_name')
brand = models.ForeignKey('Brand')
category = models.ForeignKey('Category')
manufacturer = models.ForeignKey('Manufacturer')
cost_currency = models.ForeignKey('Cost_Currency', null=True, blank=True)
cost_price = models.DecimalField(decimal_places=2, max_digits=10)
selling_currency = models.ForeignKey('Selling_Currency', null=True, blank=True)
selling_price = models.DecimalField(decimal_places=2, max_digits=10)
description = models.TextField(null=True, blank=True)
created_on = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_on = models.DateTimeField(auto_now_add=False, auto_now=True)
last_edited_by = models.ForeignKey(User, null=True, blank=True)
active = models.BooleanField(default=True)
class Meta:
unique_together = (("article_number", "size", "color"))
verbose_name = "Product"
verbose_name_plural = "*Products*"
def __unicode__(self):
return str(self.article_number) + "-" + str(self.color) + "-" + str(self.size)
class Order(models.Model):
order_status = models.ForeignKey('OrderStatus')
products = models.ManyToManyField(Product, through='OrderProductDetails', through_fields=('order','product'), null=True, blank=True)
counter = models.ForeignKey(Counter, null=True, blank=True)
order_type = models.ForeignKey('OrderType')
order_remarks = models.CharField(max_length=1000, null=True, blank=True)
order_date = models.DateTimeField(auto_now_add=True, auto_now=False)
ordered_by = models.ForeignKey(User, null=True, blank=True)
promo = models.ForeignKey('promo.Promo', verbose_name="Order for which Promotion (if applicable)", null=True, blank=True)
delivery_date = models.DateField(blank=True, null=True)
delivery_remarks = models.CharField(max_length=1000, null=True, blank=True)
updated_on = models.DateTimeField(auto_now_add=False, auto_now=True)
class Meta:
verbose_name = "Order"
verbose_name_plural = "*Orders*"
def __unicode__(self):
return str(self.id)
class OrderProductDetails(models.Model):
order = models.ForeignKey('Order')
product = models.ForeignKey('products.Product')
quantity = models.PositiveIntegerField()
selling_price = models.DecimalField(decimal_places=2, max_digits=10)
order_product_remarks = models.ForeignKey('OrderProductRemarks',blank=True, null=True)
class Meta:
verbose_name_plural = "Order - Product Details"
verbose_name = "Order - Product Details"
def __unicode__(self):
return str(self.id)
Views.py Snippet
from django.shortcuts import render, Http404, HttpResponseRedirect
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib import messages
from django.forms.models import modelformset_factory
from orders.models import Order, OrderStatus, OrderProductDetails
#login_required(login_url='/admin/login/?next=/')
def warehouseOrder(request, id):
try:
order = Order.objects.get(id=id)
products = order.products.all()
orderDetails = OrderProductDetails.objects.filter(order__id=id)
context = {'order': order, 'products': products, 'orderDetails': orderDetails}
template = 'warehouse_order.html'
return render(request, template, context)
except:
raise Http404
Template.html Snippet
<table class="table table-striped table-bordered">
<tr>
<th class="bottom-align-th">#</th>
<th class="bottom-align-th">Article No.</th>
<th class="bottom-align-th">Color</th>
<th class="bottom-align-th">Size</th>
<th class="bottom-align-th">Quantity</th>
<th class="bottom-align-th">Unit Price</th>
<th class="bottom-align-th">Remarks</th>
<th class="bottom-align-th">Barcode No.</th>
<th class="bottom-align-th">Packed</th>
</tr>
{% for product in products %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ product.article_number }}</td>
<td>{{ product.color }}</td>
<td>{{ product.size }}</td>
<td>{{ orderDetails.quantity }}</td>
<td>{{ orderDetails.selling_price }}</td>
<td>{{ orderDetails.order_product_remarks }}</td>
<td>{{ product.barcode }}</td>
<td><input type="checkbox" id="large-checkbox"></td>
</tr>
{% endfor %}
</table>
Btw, using Django 1.7.2 here.

You're looping over the wrong thing. Each Order has multiple OrderProductDetails related objects, each of which has exactly one Product. But you're looping over all products. Try something like:
{% for detail in orderDetails %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ detail.product.article_number }}</td>
<td>{{ detail.product.color }}</td>
<td>{{ detail.product.size }}</td>
<td>{{ detail.quantity }}</td>
<td>{{ detail.selling_price }}</td>
<td>{{ detail.order_product_remarks }}</td>
<td>{{ detail.product.barcode }}</td>
<td><input type="checkbox" id="large-checkbox"></td>
</tr>
{% endfor %}

Related

passing 2 different models from 2 different apps to another app table

app1/model
class Deployment(models.Model):
uid = models.CharField(max_length=255, blank=True)
target = models.CharField(max_length=255)
name = models.CharField(max_length=255, blank=True)
description = models.TextField(blank=True)
app2/model
class AccountRecord(models.Model):
name = models.CharField(max_length=255, blank=True)
file_name = models.CharField(max_length=255, blank=True)
national_id = models.CharField(max_length=255, default="")
app3/views.py
class IndexView(LoginRequiredMixin, ListView):
model = AccountRecord
template_name = "tableview/table_view.html"
paginate_by = 25
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['deployment'] = Deployment.objects.all()
return context
app3 html template
<table class="table card-table table-vcenter text-nowrap">
<thead>
<tr>
<th>Deployment</th>
<th>Account</th>
<th>National ID</th>
<th>Filename</th>
</tr>
</thead>
<tbody>
{% for account in object_list %}
<tr>
<td>DEPLOYMENT.NAME HERE!</td>
<td>{{ account.name }}</td>
<td>{{ account.national_id }}</td>
<td>{{ account.file_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I am trying to pass data from these 2 model to another apps html template.
with my current app3/views.py the table only show blank column even after i put {{ deployment.name }}
can anyone point out how to do it correctly.

i am trying to display certain items on a page, but i have a problem with the if statement

I am trying to display items that have their warehouse field == to the warehouse name, so if the warehouse they are seeing has the same name as the warehouse field of the item they should see the items. I tried the following but it isn't working.
{% for item in items %}
{% if item.warehouse == warehouse.name %}
<tr>
<td>{{ item.pk }}</td>
<td>{{ item.name }}</td>
<td>{{ item.price }}</td>
<td>{{ item.box_quantity }}</td>
<td>{{ item.Quantity_in_box }}</td>
<td>{{ item.code }}</td>
<td>{{ item.category }}</td>
<td>{{ item.supplier }}</td>
<td>{{ item.expiry }}</td>
<td>
Edit
x
</td>
</tr>
{% endif %}
{% endfor %}
when i remove the if statement as follows
{% for item in items %}
<tr>
<td>{{ item.pk }}</td>
<td>{{ item.name }}</td>
<td>{{ item.price }}</td>
<td>{{ item.box_quantity }}</td>
<td>{{ item.Quantity_in_box }}</td>
<td>{{ item.code }}</td>
<td>{{ item.category }}</td>
<td>{{ item.supplier }}</td>
<td>{{ item.expiry }}</td>
<td>
Edit
x
</td>
</tr>
{% endfor %}
i get to see all the items.
related view
def Warehouse(request, pk):
Warehouse = warehouse.objects.get(id=pk)
items = item.objects.all()
context = {
'items': items,
'warehouse': Warehouse,
}
return render(request, 'Inventory_Management/warehouse.html', context)
related url
path('warehouse/<str:pk>/', Warehouse, name="warehouse"),
complete html
{% extends 'Inventory_Management/layout.html' %}
{% block body %}
<br>
<h4>Currently Viewing {{ warehouse.name }}</h4>
Back To Warehouses
<table class="table table-hover">
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>Price</th>
<th>Box_Q</th>
<th>Q_in_box</th>
<th>Code</th>
<th>Category</th>
<th>Supplier</th>
<th>Expiry</th>
<th><a href="http://127.0.0.1:8000/admin/Inventory_Management/item/add/" role="button"
class="btn btn-primary btn-sm"> Add</a></th>
</tr>
</thead>
<tbody>
{% for item in items %}
{% if item.warehouse == warehouse.name %}
<tr>
<td>{{ item.pk }}</td>
<td>{{ item.name }}</td>
<td>{{ item.price }}</td>
<td>{{ item.box_quantity }}</td>
<td>{{ item.Quantity_in_box }}</td>
<td>{{ item.code }}</td>
<td>{{ item.category }}</td>
<td>{{ item.supplier }}</td>
<td>{{ item.expiry }}</td>
<td>
<a href="http://127.0.0.1:8000/admin/Inventory_Management/item/" class="btn btn-warning
btn-sm" role="button"> Edit</a>
<a href="http://127.0.0.1:8000/admin/Inventory_Management/item/" class="btn btn-danger
btn-sm" role="button"> x</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endblock %}
complete urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('', index, name="index"),
path('warehouses', warehouses, name="warehouses"),
path('warehouse/<str:pk>/', Warehouse, name="warehouse"),
path('customerHome', customerHome, name="customerHome"),
path('customer/<str:pk>/', Customer, name="customer"),
path('admin/Inventory_Management/warehouse/<str:pk>/', Warehouse, name="change"),
path('add_new_warehouse', add_new_warehouse, name="Nwarehouse"),
path('add_item', add_item, name="Nitem"),
path("display_search", search, name='display_search'),
]
complete views.py
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from .models import *
from .forms import *
def search(request):
items = item.objects.all()
name_q = request.GET.get('name')
box_quantity_q = request.GET.get('box_quantity')
Quantity_in_box_q = request.GET.get('quantity_in_box')
code_q = request.GET.get('code')
price_q = request.GET.get('price')
expiry_q = request.GET.get('expiry')
supplier_q = request.GET.get('supplier')
warehouse_q = request.GET.get('warehouse')
category_q = request.GET.get('category')
date_created_ = request.GET.get('date_created')
if warehouse_q != '' and warehouse_q is not None:
items = items.filter(warehouse__name__icontains=warehouse_q)
if date_created_ != '' and date_created_ is not None:
items = items.filter(date_created__icontains=date_created_)
if name_q != '' and name_q is not None:
items = items.filter(name__icontains=name_q)
if price_q != '' and price_q is not None:
items = items.filter(price__icontains=price_q)
if box_quantity_q != '' and box_quantity_q is not None:
items = items.filter(box_quantity__icontains=box_quantity_q)
if Quantity_in_box_q != '' and Quantity_in_box_q is not None:
items = items.filter(Quantity_in_box__icontains=Quantity_in_box_q)
if code_q != '' and code_q is not None:
items = items.filter(code__icontains=code_q)
if category_q != '' and category_q is not None:
items = items.filter(category__name__icontains=category_q)
if supplier_q != '' and supplier_q is not None:
items = items.filter(supplier__name__icontains=supplier_q)
if expiry_q != '' and expiry_q is not None:
items = items.filter(expiry__icontains=expiry_q)
context = {
'items' : items,
}
return render(request, 'Inventory_Management/search.html', context)
def index(request):
return render(request, 'Inventory_Management/index.html')
def warehouses(request):
Warehouses = warehouse.objects.all()
context = {
'warehouses': Warehouses,
}
return render(request, 'Inventory_Management/warehouses.html', context)
def Customer(request, pk):
orders = order.objects.all()
Customer = customer.objects.get(id=pk)
context = {
'orders': orders,
'customer': Customer,
}
return render(request, 'Inventory_Management/customer.html', context)
def customerHome(request):
orders = order.objects.all()
customers = customer.objects.all()
context = {
'orders': orders,
'customers': customers,
}
return render(request, 'Inventory_Management/customerHome.html', context)
def Warehouse(request, pk):
Warehouse = warehouse.objects.get(id=pk)
items = item.objects.all()
context = {
'items': items,
'warehouse': Warehouse,
}
return render(request, 'Inventory_Management/warehouse.html', context)
def add_item(request):
return redirect('http://127.0.0.1:8000/admin/')
def add_new_warehouse(request):
form = WarehouseForm()
if request.method == 'POST':
form = WarehouseForm(request.POST)
if form.is_valid():
form.save()
return redirect('warehouses')
context = {
'form': form,
}
return render(request, 'Inventory_Management/add_new_warehouse.html', context)
related models
class item(models.Model):
name = models.CharField(max_length=100, blank=False)
box_quantity = models.CharField(max_length=10)
Quantity_in_box = models.CharField(max_length=10)
code = models.CharField(max_length=15)
price = models.CharField(max_length=100)
expiry = models.CharField(max_length=100)
supplier = models.ForeignKey(supplier, blank=False, null=True,
on_delete=models.SET_NULL)
warehouse = models.ForeignKey(warehouse, blank=False, null=True,
on_delete=models.SET_NULL)
category = models.ForeignKey(category, blank=False, null=True,
on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class warehouse(models.Model):
name = models.CharField(max_length=20, blank=False)
description = models.CharField(max_length=1000, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
full models.py
from django.db import models
import uuid
from django.contrib import admin
class warehouse(models.Model):
name = models.CharField(max_length=20, blank=False)
description = models.CharField(max_length=1000, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class category(models.Model):
name = models.CharField(max_length=20, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class supplier(models.Model):
name = models.CharField(max_length=12, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class customer(models.Model):
name = models.CharField(max_length=12, blank=False)
phone = models.CharField(max_length=12, blank=False)
email = models.CharField(max_length=50, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class order_header(models.Model):
date_created = models.DateTimeField(auto_now_add=True, null=True)
User = models.CharField(max_length=100, blank=False, default="Seller")
Type = models.CharField(max_length=100, default="cash")
Buyer = models.ForeignKey(customer, blank=True, null=True,
on_delete=models.SET_NULL)
Note = models.CharField(max_length=100, blank=True, default="Discount: ")
Order_Id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
def __str__(self):
return 'Order Id: {self.Order_Id}'.format(self=self)
class item(models.Model):
name = models.CharField(max_length=100, blank=False)
box_quantity = models.CharField(max_length=10)
Quantity_in_box = models.CharField(max_length=10)
code = models.CharField(max_length=15)
price = models.CharField(max_length=100)
expiry = models.CharField(max_length=100)
supplier = models.ForeignKey(supplier, blank=False, null=True,
on_delete=models.SET_NULL)
warehouse = models.ForeignKey(warehouse, blank=False, null=True,
on_delete=models.SET_NULL)
category = models.ForeignKey(category, blank=False, null=True,
on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class order(models.Model):
order_head = models.ForeignKey(order_header, blank=False, null=True,
on_delete=models.SET_NULL)
items = models.ForeignKey(item, blank=False, null=True,
on_delete=models.SET_NULL)
Quantity = models.CharField(max_length=100)
date_created = models.DateTimeField(auto_now_add=True, null=True)
total = models.CharField(max_length=100)
def __str__(self):
return 'Order Customer: {self.order_head.Buyer}'.format(self=self)
help, appreciated! please help!

Can anyone help using M2M and the template properly?

I need to show the name of menu and the quantity of it.
But this webpage doesn't show even when the client's address and their name is working out right.
I've got these models(client side) in my Django project:
class Order(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE)
address = models.CharField(
max_length=100,
)
created_at = models.DateTimeField(auto_now_add=True)
items = models.ManyToManyField(
Menu,
through='OrderItem',
through_fields=('order', 'menu'),
)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
menu = models.ForeignKey(Menu, on_delete=models.CASCADE)
count = models.PositiveSmallIntegerField()
and the template page like below.
{% for order in order_set %}
<tr>
<td>{{ order.client.name }}</td>
<td>{{ order.address }}</td>
<td>{% for item in order.items_set.all %}{{ item }}{% endfor %}</td>
<td>{{ order.item_set.all.count }}</td>
</tr>
{% endfor %}
</table>
Models(partner side) like below.
class Menu(models.Model):
partner = models.ForeignKey(
Partner,
on_delete=models.CASCADE,
)
image = models.ImageField(
verbose_name="메뉴 이미지"
)
name = models.CharField(
max_length=50,
verbose_name="메뉴 이름"
)
price = models.PositiveIntegerField(
verbose_name="가격"
)
Can anyone help?
Try this:
{% for order in order_set %}
<tr>
<td>{{ order.client.name }}</td>
<td>{{ order.address }}</td>
<td>{% for item in order.items.all %}{{ item }}{% endfor %}</td>
<td>{{ order.items.all.count }}</td>
</tr>
{% endfor %}
i.e., replace order.items_set.all with order.items.all. There is no relationship defined by items_set. The field you've defined on your Order model is items, so that is what you need to access.
The FOO_set approach is used for relationships in reverse on things like foreign keys. In this case you're following a relationship forward.

Append to QuerySet Items

Item Model (represents a product, like a MacBook)
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=100)
manufacturer = models.ForeignKey('Manufacturer', blank=True, null=True, on_delete=models.SET_NULL)
introduction = models.DateField(auto_now=True)
is_retired = models.BooleanField(default=False)
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.name
OnHand Model (represents a serialized MacBook)
class OnHand(models.Model):
name = models.CharField(max_length=100)
serial = models.CharField(max_length=80)
asset = models.CharField(max_length=20)
product = models.ForeignKey(Item, blank=True, null=True, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.serial
Index View
Index Function
def index(request):
items = Item.objects.all()
context = {
'items':items,
}
print(items)
return render(request, 'index.html', context)
Template/Table
<table class="table table-hover">
<thead class="thead-light">
<tr>
<th>Item Id</th>
<th>Title</th>
<th>Manufacturer</th>
<th>On Hand</th>
<th>Category Id</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>{{ item.pk }}</td>
<td>{{ item.name }}</td>
<td>{{ item.manufacturer }}</td>
<td>{{ item.quanity }}</td>
</tr>
{% endfor %}
</tbody>
</table>
This application is an Inventory Management System which can take in Items such as a MacBook Pro or iPhone 6, and OnHands which are serialized instances of these Items. In my Index Function I am passing the result of an all() query to the Index View in context.
I can query OnHand.objects.filter(product_id=item.pk) to get the quanity of each Item, however, in my current way of doing things I'm unsure how I can pass that value to the front end while keeping its relationship if that makes sense.
I would like item.quanity to essentially represent the quanity of that particular item. What am I looking for? My initial thought would be to append to the QuerySet but I'm not sure how to do so.
You're looking for annotate.
from django.db.models import Count
items = Item.objects.annotate(
quantity=Count('onhand_set__id'),
)
Depending on your usage, you may need to pass distinct=True to Count.

filtering objects in descending order in django

I am trying to show a table of schools in a cluster(city or town) in a descending order with respect to school average marks.
<table class="table">
<thead>
<tr>
<th>School</th>
<th>Strength</th>
<th>Average</th>
</tr>
</thead>
<tbody>
{% for school in school_order %}
<tr>
<td>{{ school.school_name }}</td>
<td>{{ school.strength }}</td>
<td>{{ school.get_average }}</td>
</tr>
{% endfor %}
</tbody>
</table>
This is the table I'm trying to display in my template
school_order = cluster.school_set.all().order_by('-get_average')
This is how I'm trying to get school_order in view.py
get_average is not a field for model school but it is a method I used in the model.
class School(models.Model):
state = models.ForeignKey(State, on_delete=models.CASCADE)
region = ChainedForeignKey(Region, chained_field="state",chained_model_field="state", show_all=False, auto_choose=True, sort=False, on_delete=models.CASCADE)
cluster = ChainedForeignKey(Cluster, chained_field="region",chained_model_field="region", show_all=False, auto_choose=True, sort=False, on_delete=models.CASCADE)
school_name = models.CharField(max_length=250)
facilitator = models.CharField(max_length=250)
f_number = models.IntegerField()
f_email = models.EmailField()
school_logo = models.FileField(default='')
strength = models.IntegerField()
def get_average(self):
return self.avergae_set.latest('average_date').average_value
This is my model for school.
The error I'm getting is cannot resolve keyword 'get_average' into field.
Please help!
You can't use Django ORM's orderby for non model field. You can convert the queryset to list and do sort in python.
school_order = list(cluster.school_set.all())
.sort(key=lambda x: x.get_average, reverse=True)
Other options are you can you select extra or annotate.
Ref: https://docs.djangoproject.com/en/1.11/ref/models/querysets/#annotate

Categories

Resources