Django models caching - python

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.

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.

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

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 select_related: How to display related table data in a template

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 %}

Categories

Resources