Django select_related: How to display related table data in a template - python

I am having trouble displaying fields of related tables in my template when using select_related()
Here is my model:
class Customer(models.model):
customer_name = models.CharField(max_length=500)
class Orders(models.model):
cust_id = models.ForeignKey(Customers)
invoice_number = models.IntegerField()
invoice_creation_date = models.DateTimeField('Invoice Created Date')
class Products(models.Model):
name = models.CharField(max_length=500)
description = models.CharField(max_length=500)
price = models.DecimalField(max_digits=20, decimal_places=2)
class Orders_Products(models.Model):
order_id = models.ForeignKey(Orders)
product_id = models.ForeignKey(Products)
quantity = models.IntegerField(default=0)
Here is my view:
def home(request):
list_of_orders = Orders_Products.objects.select_related()
template = 'erp_app/home.html'
context = RequestContext(request, {'list_of_orders': list_of_orders})
return render(request, template, context)
How do I represent related fields from Orders and Products, and especially Customers in a template. E.g. I want to display Orders.invoice_number, Products.name and Customer.customer_name from the same related record.
For example:
{% for order in list_of_orders %}
<tr>
<td>{{ order.orders.invoice_number }}</td>
<td>{{ order.products.name }}</td>
<td>{{ order.customers.customer_name }}</td>
</tr>
{% endfor %}

I figured it out. I'm leaving this question and answer here for the next poor soul who has to nut his way through this conundrum.
{% for order in list_of_orders %}
<tr>
<td>{{ order.order_id.cust_id.customer_name }}</td>
<td>{{ order.order_id.invoice_number }}</td>
<td>{{ order.order_id.invoice_creation_date }}</td>
<td>{{ order.product_id.price }}</td>
</tr>
{% endfor %}

Related

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.

Django Listview - Filter and Pagination

I'm new to django. I'm trying to create two table, first one with the lastest added products filter by publication_date and second one with the upcoming products filter by release_date.
Here my homepage.html code :
...
{% for prodotto in products %}
<tr>
<td>{{ prodotto.title }}</td>
<td>{{ prodotto.description }}</td>
<td>{{ prodotto.publication_date|date:"d/m/Y" }}</td>
<td>{{ prodotto.release_date|date:"d/m/Y" }}</td>
</tr>
{% endfor %}
...
...
{% for prodotto in products %}
<tr>
<td>{{ prodotto.title }}</td>
<td>{{ prodotto.description }}</td>
<td>{{ prodotto.publication_date|date:"d/m/Y" }}</td>
<td>{{ prodotto.release_date|date:"d/m/Y" }}</td>
</tr>
{% endfor %}
here my model.py :
class Products(models.Model):
...
title = models.CharField(max_length=100)
publication_date = models.DateTimeField(auto_now_add=True)
description = models.CharField(max_length=1000)
slug = models.SlugField(unique=True)
release_date = models.DateTimeField()
...
here my view.py :
class home(ListView):
queryset = Products.objects.all()
template_name = 'homepage.html'
context_object_name = "products"
Currently i'm able to only show all the products without filtering.
I'm trying to also add pagination only in the first table,but I don't have an idea how to filter and add pagination in my homepage.html.
I've tried adding pagination by adding paginate_by = 5 into view.py but with this method,it's adding pagination in both tables.
You can do this directly in your template:
{% for prodotto in products|slice:":5" %}
<tr>
<td>{{ prodotto.title }}</td>
<td>{{ prodotto.description }}</td>
<td>{{ prodotto.publication_date|date:"d/m/Y" }}</td>
<td>{{ prodotto.release_date|date:"d/m/Y" }}</td>
</tr>
{% endfor %}

Django: display multiple objects on a single page

I have a lot of data from my fantasy basketball league displayed at index.html
When I click a player name, I am taken to that player's single season's statistics.
What I want to happen, when I click a player name, is for all of that player's career statistics to show up, not just a single year.
What's the best method for going about doing that? I've been stuck on this for about two weeks now, lol
Note: each 'player' object contains a separate "game_id" that belongs to each real-life player (e.g. each player object in this list of Aaron Brooks objects has the same "game_id"), but I haven't been able to figure out how to use it yet!
Thanks in advance!
Views.py:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'players_list'
def get_queryset(self):
return Player.objects.order_by('full_name', 'season', 'team', '-ppg', 'full_name')
class PlayerView(generic.DetailView):
model = Player
template_name = 'polls/player.html'
Models.py:
class Player(models.Model):
def __str__(self):
return self.full_name
first_name = models.CharField(max_length=200, default='')
surname = models.CharField(max_length=200, default='')
full_name = models.CharField(max_length=200, default='')
nba_live_id = models.IntegerField(default=0)
season = models.CharField(max_length=4, default='')
team = models.CharField(max_length=3, default='')
pos = models.CharField(max_length=2, default='')
gp = models.IntegerField(default=0)
gs = models.IntegerField(default=0)
ppg = models.FloatField(default=0)
rpg = models.FloatField(default=0)
apg = models.FloatField(default=0)
spg = models.FloatField(default=0)
bpg = models.FloatField(default=0)
Index.html:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />
{% if players_list %}
<table>
<tr>
<td>Season</td>
<td>Team</td>
<td>GP</td>
<td>GS</td>
<td>Pos</td>
<td>Player Name</td>
<td>PPG</td>
<td>RPG</td>
<td>APG</td>
<td>BPG</td>
<td>SPG</td>
<td></td>
</tr>
{% for player in players_list %}
<tr>
<td>{{ player.season }}</td>
<td>{{ player.team }}</td>
<td>{{ player.gp }}</td>
<td>{{ player.gs }}</td>
<td>{{ player.pos }}</td>
<td>{{ player.full_name }}</td>
<td>{{ player.ppg }}</td>
<td>{{ player.rpg }}</td>
<td>{{ player.apg }}</td>
<td>{{ player.bpg }}</td>
<td>{{ player.spg }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
Player.html:
<h1>{{ player.full_name }}</h1>
<h1>{{ question.question_text }}</h1>
<table>
<tr>
<td>Season</td>
<td>Team</td>
<td>GP</td>
<td>GS</td>
<td>Pos</td>
<td>Player Name</td>
<td>PPG</td>
<td>RPG</td>
<td>APG</td>
<td>BPG</td>
<td>SPG</td>
<td></td>
</tr>
<tr>
<td>{{ player.season }}</td>
<td>{{ player.team }}</td>
<td>{{ player.gp }}</td>
<td>{{ player.gs }}</td>
<td>{{ player.pos }}</td>
<td>{{ player.full_name }}</td>
<td>{{ player.ppg }}</td>
<td>{{ player.rpg }}</td>
<td>{{ player.apg }}</td>
<td>{{ player.bpg }}</td>
<td>{{ player.spg }}</td>
</tr>
</table>
Your model structure is wrong. You need to separate out the season information into a new model, so you have Player and PlayerSeason linked by a ForeignKey. (You might also want to separate out Team too, and potentially even Season itself, but that's outside the scope of this question.)
So, PlayerSeason might look like this:
class PlayerSeason(models.Model):
player = models.ForiegnKey('Player')
team = models.CharField(max_length=3, default='')
pos = models.CharField(max_length=2, default='')
gp = models.IntegerField(default=0)
gs = models.IntegerField(default=0)
ppg = models.FloatField(default=0)
rpg = models.FloatField(default=0)
apg = models.FloatField(default=0)
spg = models.FloatField(default=0)
bpg = models.FloatField(default=0)
Now in the template you can iterate over all playerseasons for an individual player:
<h1>{{ player.full_name }}</h1>
<h1>{{ question.question_text }}</h1>
<table>
...
{% for season in player.playerseason_set.all %}
<tr>
<td>{{ player.gp }}</td>
...
</tr>
{% endfor %}
You'll want to set up your admin site so that PlayerSeason can be edited inline with Player, as well.

Django - Foreign Key not working

I'm trying to display some data on a webpage using a foreach loop and django.
I do not seem to understand how to use a lookup table that I have created in my Database.
These are the columns from the DB:
budget_audit_table:
-BudgetID
-BudgetTypeID <- Foreign Key
-ObjectAuditID
-CustomerID
-DateOfTransaction
-BudgetObject
-Amount
budget_type:
-BudgetTypeID
-BudgetType
As you can probably assume in the model.py, the BudgetTypeID is a foreign key.
In the budget_type table I currently have 2 rows:
- Expense: ID 1
- Income: ID 2
Now the problem I'm having is I have searched for a few days now trying to understand Django's API more and I'm struggling to understand how do I for each row that is displayed from the budget_audit_table, how do I instead of displaying the BudgetTypeID (eg 1), it displays the BudgetType (eg Expense)?
Here is my view & template
view.py
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.template import RequestContext, loader
from models import BudgetAuditTable
from models import BudgetType
#login_required
def index(request):
budgetauditlist = BudgetAuditTable.objects.order_by('-budgetid')
template = loader.get_template('budget/budget.html')
context = RequestContext(request, {
'budgetauditlist': budgetauditlist,
})
return HttpResponse(template.render(context))
Template
{% for budgetauditobject in budgetauditlist %}
<tr>
<td>{{ budgetauditobject.budgetid }}</td>
<td>{{ budgetauditobject.budgettypeid }}</td>
<td>{{ budgetauditobject.objectauditid }}{{ budgetauditobject.customerid }}</td>
<td>{{ budgetauditobject.amount }}</td>
</tr>
{% endfor %}
models.py
class BudgetAuditTable(models.Model):
budgetid = models.IntegerField(db_column='BudgetID', primary_key=True)
budgettypeid = models.ForeignKey('BudgetType', db_column='BudgetTypeID', blank=True, null=True)
objectauditid = models.IntegerField(db_column='ObjectAuditID', blank=True, null=True)
customerid = models.IntegerField(db_column='CustomerID', blank=True, null=True)
dateoftransaction = models.DateField(db_column='DateOfTransaction', blank=True, null=True)
budgetobject = models.CharField(db_column='BudgetObject', max_length=255, blank=True)
amount = models.DecimalField(db_column='Amount', max_digits=10, decimal_places=2, blank=True, null=True)
class Meta:
managed = False
db_table = 'budget_audit_table'
class BudgetType(models.Model):
budgettypeid = models.IntegerField(db_column='BudgetTypeID', primary_key=True)
budgettype = models.CharField(db_column='BudgetType', max_length=25, blank=True)
class Meta:
managed = False
db_table = 'budget_type'
In your template try:
{% for budgetauditobject in budgetauditlist %}
<tr>
<td>{{ budgetauditobject.budgetid }}</td>
<td>{{ budgetauditobject.budgettypeid.budgettype }}</td>
<td>{{ budgetauditobject.objectauditid }}{{ budgetauditobject.customerid }}</td>
<td>{{ budgetauditobject.amount }}</td>
</tr>
{% endfor %}
Furthermore you should rename your BudgetType ForeignKey field in your model simply to BudgetType since your ForeignKey relation represents another entity.
See this link for the relationship lookups.
budgetauditobject.budgettypeid specify a BudgetType object, you should use the attributes under BudgetType like this:
{{ budgetauditobject.budgettypeid.budgettype }}
{{ budgetauditobject.budgettypeid.budgettypeid }}
So, you need to modify the template like this:
{% for budgetauditobject in budgetauditlist %}
<tr>
<td>{{ budgetauditobject.budgetid }}</td>
<td>{{ budgetauditobject.budgettypeid }}</td>
<td>{{ budgetauditobject.objectauditid }}{{ budgetauditobject.customerid }}</td>
<td>{{ budgetauditobject.amount }}</td>
</tr>
{% endfor %}
{{ budgetauditobject.budgettypeid.budgettype }}
Its quite simple, just follow the relationship, like this:
{% for budgetauditobject in budgetauditlist %}
<tr>
<td>{{ budgetauditobject.budgetid }}</td>
<td>{{ budgetauditobject.budgettypeid.budgettype }}</td>
<td>{{ budgetauditobject.objectauditid }}{{ budgetauditobject.customerid }}</td>
<td>{{ budgetauditobject.amount }}</td>
</tr>
{% endfor %}
The . syntax will allow you to follow and query items from the linked table. budgetauditobject.bugettypeid.budgettype means "get the bugettype field's value of the bugettypid that corresponds to this budgetauditobject"
You can try changing
{{ budgetauditobject.budgettypeid }}
to
{{ budgetauditobject.budgettypeid.budgettype }}

Django models caching

In models.py I have models Order and Item, Item containing price and weight:
class Item(models.Model):
name = models.CharField(u'Name', max_length=255)
article = models.CharField(u'Article', max_length=255)
price = models.PositiveIntegerField(u'Price')
weight = models.PositiveIntegerField(u'weight', blank=True, null=True, default=None)
class Order(models.Model):
item = models.ForeignKey(Item, verbose_name=u'Item')
count = models.PositiveIntegerField(u'Count')
user = models.ForeignKey(User, verbose_name=u'User')
def sum(self):
return self.count*self.item.price
def weight(self):
return self.count*self.item.weight
In views.py I select my orders:
#render_to('app/purchase_view.html')
def purchase_view(request):
myorders = Order.objects.select_related().filter(user=request.user).all()
context.update({
'myorders':myorders,
})
And in template:
{% for myorder in myorders %}
<td>{{ myorder.item.article }}</td>
<td style="text-align:left;">{{ myorder.item.name }}</td>
<td>{{ myorder.item.price }}</td>
<td>{{ myorder.count }}</td>
<td>{{ myorder.sum }}</td>
<td>{{ myorder.weight }}</td>
</td>
</tr>
{% endfor %}
so, django generates for each parameter: myorder.sum, myorder.weight - similar queries. Is there something for cache in Order model sum and weight.
I am not sure what you are actually asking, but quersets in django are lazy. This means that django doesn't actually execute the query until the queryset is evaluated.
This might be what you are seeing when you say its cached.
What makes you think Django is doing queries to get order.price and order.weight? It isn't. It's doing a single query, to get the order and its associated item (because you used select_related). Everything after that is simply operations on data it already has.

Categories

Resources