Django prefetch_related outputs None - python

I'm new to Django. I am making a simple store.
Currently I am working on the Order section.
Every Order has Order Items inside it. Every order item has some values and a product id.
What I am trying to display on the index.html, is the orders and its items inside it. However order.items always outputs order.OrderItem.None
views.py
class IndexView(generic.ListView):
template_name = 'order/index.html'
context_object_name = 'all_orders'
def get_queryset(self):
return Order.objects.all().prefetch_related('items')
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
return context
views.py
# Create your models here.
class Order(models.Model):
user = models.ForeignKey(User, related_name='orders')
created_at = models.DateTimeField(auto_now_add=True, null=True)
class OrderItem(models.Model):
product = models.ForeignKey(Product)
order = models.ForeignKey(Order, related_name='items')
item_name = models.CharField(max_length=255, null=True, blank=True)
item_price_in_usd = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
def __str__(self):
return self.product.name
index.html
{% for order in all_orders %}
<tr>
<td>{{ order}}</td>
<td>{{ order.created_at}}</td>
<td>{{ order.items}}</td>
</tr>
{% endfor %}

Ok, I have found to solution. Apparently you have to add .all
{% for order in all_orders %}
<tr>
<td>{{ order}}</td>
<td>{{ order.created_at}}</td>
<td>
{% for items in order.items.all %}
<td>{{ items.item_name}}</td>
{% endfor %}
</td>
</tr>
{% endfor %}

Related

i have to make a relation between movie and actor without using manytomany field i have to use only foreign key in django i've write this code so far

models.py
class Movielist(models.Model) :
Title = models.CharField(max_length=1000)
Description = models.TextField(blank=True)
ReleaseDate = models.DateTimeField(verbose_name='Release Date', blank=True)
# NoOfActors = models.IntegerField()
Upvote = models.IntegerField(default=0)
Downvote = models.IntegerField(default=0)
def __str__(self):
return self.Title
class Actorlist(models.Model):
Name = models.CharField(max_length=1000)
DateofBirth = models.DateTimeField(verbose_name='Date of Birth',blank=True)
# NoOfActors = models.IntegerField()
def __str__(self):
return self.Name
class ActorInMovie(models.Model):
Movie = models.ForeignKey(Movielist, default=1, on_delete=models.CASCADE, blank=True)
Actor = models.ForeignKey(Actorlist, default=1, on_delete=models.CASCADE, blank=True)
def __str__(self):
return self.Movie.Title
views.py
def Movie_Detail(request):
MovieName = Movielist.objects.all()
tablelist = ActorInMovie.objects.all()
return render(request, 'Collection/index.html', {'MovieName':MovieName, 'tablelist':tablelist})
index.html
<table border="solid">
<th>Name</th>
<th>Release Date</th>
<th>Actors</th>
{% for data in MovieName %}
<tr>
<td>{{ data.Title }}</td>
<td>{{ data.ReleaseDate }}</td>
<td>
<ul>
{% for name in tablelist %}
<li>{{ name.Actor.Name }}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</table>
**i have getting this out put can any any one tell me how to filter this data only my movie id i would like if someone come and help me in solving this problem
[this is the output what i am getting but i want filter actors name by movielist.id][1]
[1]: https://i.stack.imgur.com/BlAuP.png**
You are selecting all the objects in ActorInMovie into tablelist, and not just the related ones. You don't need the tablelist at all. Instead:
{% for data in MovieName %}
<tr>
<td>{{ data.Title }}</td>
<td>{{ data.ReleaseDate }}</td>
<td>
<ul>
{% for movie_actor in data.ActorInMovie %}
<li>{{ movie_actor.Actor.Name }}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
You might also need to use related_name in your ActorInMovie model to tell django how you'll identify the related fields:
Movie = models.ForeignKey(Movielist, default=1, on_delete=models.CASCADE, blank=True, related_name='ActorInMovie)
Since you're going to print all the actors of every movie, it's a good idea to use prefetch_related(Another ref) to achieve better performance, but it's not required if you don't have a lot of data.

how to call property method from model class to html in django

Im making a django app, and its basically an admin site, i have an app called calculator, inisde it i have 3 models Transaction, FamilyGroup and FamilyMember, each model has some property methods for calculation purposes. here are the models for more clearness :
class Transaction(models.Model):
chp_reference = models.CharField(max_length=50, unique=True)
rent_effective_date = models.DateField(null=True, blank=True)
income_period = models.CharField(max_length=11)
property_market_rent = models.DecimalField(max_digits=7)
#property
def ftb_combined(self):
ftb_combined = 0
for family_group in self.familygroup_set.all():
ftb_combined += family_group.ftb_combined
return ftb_combined
class FamilyGroup(models.Model):
name = models.CharField(max_length=10)
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
last_rent = models.DecimalField(max_digits=7)
#property
def additional_child_combined(self):
return (self.number_of_additional_children
or 0) * self.maintenance_rate_additional_child
class FamilyMember(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
family_group = models.ForeignKey(FamilyGroup, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=100, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
income = models.DecimalField(max_digits=6)
#property
def weekly_income(self):
if self.transaction.income_period == 'Weekly':
return self.income
return (self.income or 0) / 2
this is how my models are connected, now i made a method in views.py as below:
def transaction_print(request, transaction_id):
transaction = Transaction.objects.get(id=transaction_id)
return render(request, 'report.html', {'transaction':transaction})
I want to make a report in report.html, 1 report for each transaction, and the transaction can have many FamilyGroups and FamilyMember, and will include almost all the data from the models and the property methods inside it.
here what i thought in the report.html
<table class="table">
<thead class="thead-dark">
<tr>
<th>CHP Reference </th>
<th>Rent Effective From (dd/mm/yyyy)</th>
<th>CRA Fortnightly Rates valid for 6 months from</th>
<th>Market Rent of the Property </th>
<th>Number of Family Groups </th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ transaction.chp_reference }} </td>
<td>{{ transaction.rent_effective_date }} </td>
<td>0</td>
<td>{{ transaction.property_market_rent }}</td>
<td>{{ transaction.number_of_family_group }}</td>
</tr>
</tbody>
{% for family_group in transaction.family_group_set.all %} ??
{% for m in family_group.transaction.family_group_set.all %} ??
</table>
Im really not sure how to perform the nested loop to iterate through the FamilyGroup and FamilyMember inside the transaction report.html would appreciate a hint how this be done.
According to the documentation Django sets the name to MODELNAME_set. However you can still use the related_name property to set a name for your backward reference (you will still be able to use MODELNAME_set as well).
Here's how to achieve it using related_name:
models.py
class FamilyGroup(models.Model):
name = models.CharField(max_length=10)
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE, related_name="family_groups") # Notice the related_name here as it will be used later on
last_rent = models.DecimalField(max_digits=7)
# ...
class FamilyMember(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE, related_name="family_members") # Notice the related_name
family_group = models.ForeignKey(FamilyGroup, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=100, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
income = models.DecimalField(max_digits=6)
# ...
Now you can loop through them like so:
report.html
{% for family_group in transaction.family_groups.all %}
{{ family_group.name }}
{% endfor %}
{% for family_member in transaction.family_members.all %}
{{ family_member.name }}
{% endfor %}

How to properly make a query in Django?

I've ran into a little problem. I want to construct a proper queryset to get values which represent the number of the expenses per category to display this like that.
This is what I got now:
class CategoryListView(ListView):
model = Category
paginate_by = 5
def get_context_data(self, *, category_object_list=None, **kwargs):
**categories = Category.objects.annotate(Count('expense'))
queryset = categories.values('expense__count')**
return super().get_context_data(
category_object_list=queryset,
**kwargs)
Of course it doesnt work and I have terrible table like this. I suppose the problem isn't in HTML but in my absolutely wrong query... What should I do?
This is my HTML in case it would be needed:
{% for category in object_list %}
<tr>
<td>
{{ category.name|default:"-" }}
</td>
<td>
{% for number in category_object_list %}
{{ number.expense__count }}
{% endfor %}
</td>
<td>
edit
delete
</td>
{% endfor %}
</tr>
Also my models.py:
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return f'{self.name}'
class Expense(models.Model):
class Meta:
ordering = ('-date', '-pk')
category = models.ForeignKey(Category, null=True, blank=True,
on_delete=models.CASCADE)
name = models.CharField(max_length=50)
amount = models.DecimalField(max_digits=8, decimal_places=2)
date = models.DateField(default=datetime.date.today, db_index=True)
def __str__(self):
return f'{self.date} {self.name} {self.amount}'
You can try like this within your template with the reverse look up of
Foregin Keys. See the docs for more detail.
{% for category in object_list %}
<tr>
<td>
{{ category.name|default:"-" }}
</td>
<td>
{{category.expense_set.all.count}}
</td>
<td>
edit
delete
</td>
{% endfor %}
</tr>
Now in the view you can just pass all the categories with the ListView
class CategoryListView(ListView):
model = Category
paginate_by = 5

How to make a filtered summary in django template involving two models linked with foreign key?

I am currently learning django and below is the current setup:
models.py
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Delivered', 'Delivered'),
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
status = models.CharField(max_length=200, null=True, choices=STATUS, default="Pending")
def __str__(self):
return self.product.name
views.py
def home(request):
orders = Order.objects.all().order_by('-date_created')
customers = Customer.objects.all()
c_pending = orders.filter(status='Pending').all()
context = {
'orders': orders,
'customers': customers,
'c_pending': c_pending,
}
return render(request, 'home.html', context)
home.html
{% for customer in customers %}
<tr>
<td>{{customer.name}}</td>
<td>{{customer.phone}}</td>
<td>{{customer.order_set.count}}</td>
<td>{{c_pending.count}}</td>
</tr>
{% endfor %}
One to third column work flawlessly, except fourth column. The problem is I wish to display in fourth column the no. of orders which is under pending status for each customer but it indeed shows up the total no. of pending orders as a whole. What steps I am missing in order for django template properly extract the no. of orders for each customer under pending status. Any help is highly appreciated. Thanks.
c_pending is just the queryset of all pending orders, not per se of that customer. You can annotate the queryset with the number of pending orders:
from django.db.models import Count, Q
def home(request):
orders = Order.objects.all().order_by('-date_created')
customers = Customer.objects.annotate(
total_orders=Count('order'),
total_pending=Count('order', filter=Q(order__status='Pending'))
)
context = {
'orders': orders,
'customers': customers,
'c_pending': c_pending,
}
return render(request, 'home.html', context)
In the view, you then render this with:
{% for customer in customers %}
<tr>
<td>{{ customer.name }}</td>
<td>{{ customer.phone }}</td>
<td>{{ customer.total_orders }}</td>
<td>{{ customer.total_pending }}</td>
</tr>
{% endfor %}

Iterating through Django ModelForm Instance in Template

I am iterating through a queryset in the template using template tags to show the data of existing database entries (i.e. Customer Orders). However, I want to allow users to edit one of these fields (i.e. Delivery Remarks) for each Customer Order.
My approach was to use ModelForm but I cannot iterate the instances for each form as I iterate through the Customer Orders in the template.
I tried to iterate through an instance to a ModelForm but I get stuck because I am unable to pass the instance to a ModelForm in a template when in context(in views.py) it is the entire queryset that is passed to the template, not an instance. Perhaps I am approaching this problem the wrong way.
My code is below and I am thankful for any help you can give:
Models.py
from django.db import models
from products.models import Product
from counters.models import Counter
from promo.models import Promo
from django.contrib.auth.models import User
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)
class OrderProductRemarks(models.Model):
order_product_remarks = models.CharField(max_length=240, null=False, blank=False)
class Meta:
verbose_name_plural = "Order Product Remarks"
def __unicode__(self):
return str(self.order_product_remarks)
class OrderStatus(models.Model):
order_status_number = models.PositiveIntegerField(null=False, blank=False)
order_status = models.CharField(max_length=100, null=False, blank=False)
class Meta:
verbose_name_plural = "Order Status"
def __unicode__(self):
return str(self.order_status_number) + ". " + str(self.order_status)
class OrderType(models.Model):
order_type = models.CharField(max_length=100, null=False, blank=False)
class Meta:
verbose_name_plural = "Order Type"
def __unicode__(self):
return str(self.order_type)
Views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.admin.views.decorators import staff_member_required
from orders.models import Order
from orders.forms import OrderForm, RemarksForm
from products.models import Product
#login_required(login_url='/admin/login/?next=/')
def warehouseOrders(request):
queryset = Order.objects.filter(order_status__order_status_number = 2) #Filter through default queryset manager with filter through FK
form = RemarksForm(request.POST or None)
if form.is_valid():
form.save()
context = {'queryset': queryset, 'form': form}
template = 'warehouse_orders.html'
return render(request, template, context)
Forms.py
from django import forms
from .models import Order
class RemarksForm(forms.ModelForm):
class Meta:
model = Order
fields = ['delivery_remarks']
Template.html
{% extends 'base_frontend.html' %}
{% load crispy_forms_tags %}
{% block head_title %}
({{ queryset|length}}) Warehouse Orders
{% endblock %}
{% block head_styles %}
{% endblock %}
{% block jquery %}
{% endblock %}
{% block content %}
<h1>Orders to Pack</h1>
<br>
{% for item in queryset %}
Order ID: {{ item }}<br>
<b>Order Status: {{ item.order_status }}</b><br>
Counter: {{ item.counter }}<br>
Order Type: {{ item.order_type }}<br>
Order Remarks: {{ item.order_remarks }}<br>
Order Date: {{ item.order_date }}<br>
Sales Rep: {{ item.ordered_by }}<br>
Promo: {{ item.promo }}<br>
Delivery Date: {{ item.delivery_date }}<br>
<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">Barcode No.</th>
<th class="bottom-align-th">Color</th>
<th class="bottom-align-th">Free Size</th>
<th class="bottom-align-th">3MTH<br>110<br>S</th>
<th class="bottom-align-th">6MTH<br>120<br>M</th>
<th class="bottom-align-th">9MTH<br>130<br>L</th>
<th class="bottom-align-th">------<br>140<br>XL</th>
<th class="bottom-align-th">------<br>150<br>XXL</th>
<th class="bottom-align-th">Unit Price</th>
<th class="bottom-align-th">Total Quantity</th>
<th class="bottom-align-th">Remarks</th>
</tr>
{% for product in item.products.all %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ product.article_number }}</td>
<td>{{ product.barcode }}</td>
<td>{{ product.color }}</td>
<td>{{ product.quantity }}</td>
</tr>
{% endfor %}
</table>
<br>
Delivery Remarks: {{ item.delivery_remarks }}<br>
{% if form %}
<form method="POST" action=""> {% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Save" class="btn btn-default"/>
</form>
{% endif %}
<br>
<button class="btn btn-success btn-lg">Start Packing</button>
<button class="btn btn-primary btn-lg">Finish Packing</button>
<button class="btn btn-danger btn-lg">Send Order to HQ for Changes</button>
{% endfor %}
{% endblock %}
Btw, using Django 1.7.2 here.

Categories