I have 2 fields, total annual leaves and annual leaves taken,
using .aggregate(Sum()) I've calculated the of total annual leaves taken for an employee.
but now I want to calculate the remaining leaves available for the user, which is
total annual leaves - total annual leaves taken
but I'm having trouble doing it because the annual_taken is a string and not a float
Its giving me this error :
unsupported operand type(s) for -: 'float' and 'str'
How can I fix this? Any help is much appreciated
Below is my code :
model.py
class LeavesEntitlement(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='+')
type = models.ForeignKey(LeavesType, on_delete=models.CASCADE, related_name='+')
days = models.FloatField(null=True, blank=True)
class Leave(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='+')
type = models.ForeignKey(LeavesType, on_delete=models.CASCADE, related_name='+')
duration = models.FloatField()
View.py
def my_leaves_view(request):
annual = LeavesEntitlement.objects.all().filter(employee=request.user.profile.employee.id, type=1)
annual_taken = Leave.objects.all().filter(employee=request.user.profile.employee.id, type=1).aggregate(Sum('duration'))
for annual_field in annual:
for field in annual_taken:
annual_available = annual_field.days - field
context = {'form': form,
'annual': annual,
'annual_taken': annual_taken,
'annual_available': annual_available
}
return render(request, 'hrm/my_leaves/my_leaves_content.html', context)
HTML
<table id="my_entitlement_table" class="display table table-hover table-responsive" width="100%">
<thead>
<tr>
<th class="small text-muted text-uppercase"><strong>Leave Type</strong></th>
<th class="small text-muted text-uppercase"><strong>Total</strong></th>
<th class="small text-muted text-uppercase"><strong>Taken</strong></th>
<th class="small text-muted text-uppercase"><strong>Available</strong></th>
</tr>
</thead>
<tbody>
{% for annual_field in annual %}
<tr>
<td>{{annual_field.days}}</td>
<td>{{annual_taken.duration__sum}}</td>
<td>{{annual_available}}</td>
</tr>
{% endfor %
</tbody>
In field you have a dict, so
with some refactoring (don't need all if use filter, and more readable if once define employee) your code may look:
employee = request.user.profile.employee.id
annual = LeavesEntitlement.objects.filter(employee=employee, type=1)
annual_taken = Leave.objects.filter(employee=employee, type=1).aggregate(Sum('duration'))
for annual_line in annual:
annual_available = annual_line.days - annual_taken.get('duration__sum', 0)
Hope it helps.
The aggregation sum return a key value pair so you have to get the value from dict.
annual_taken = Leave.objects.all()
.filter(employee=request.user.profile.employee.id,
type=1).aggregate(Sum('duration'))
then
sum_taken = annual_taken.get('duration__sum')
Also this loop in your code
for field in annual_taken:
annual_available = annual_field.days - field
is wrong. You are trying to iterate over a dict. Removing this loop and using sum_taken will work no need to loop
Related
I'm having trouble with Django queryset. First of all, what I want to do is to receive from the customer which discount coupons (dc for short) he/she used and then compare with the ones already in the system. And I did manage to do it with 1
my view:
#login_required(login_url='login')
def cupons(request):
produtos = Produto.objects.all()
cliente = Cliente.objects.get(user=request.user)
pedido = Pedido.objects.all().get(cliente=cliente)
return render(request, 'cupons.html', {'lista': produtos, 'venda': pedido.produto.cupom})
The succesfull result
P.S: There are 2 Usado (Used) because they have the same "dc"
The problem starts when the user used 2 or more "dc", it says that get() received more than 1 result and after some research I found that I need to use filter, but someone can explain me how can achieve the same result using filter ?
My classes are Cliente (Client), Produto (Product) and Pedido (Order).
my model:
class Cliente(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
class Produto(models.Model):
STATUS = (
('Novo', 'Novo'),
('Expirado', 'Expirado'),
('Usado', 'Usado'),
)
...
...
cupom = models.CharField(max_length=200, null=True)
...
class Pedido(models.Model):
cliente = models.ForeignKey(Cliente, null=True, on_delete=models.SET_NULL)
produto = models.ForeignKey(Produto, null=True, on_delete=models.SET_NULL)
...
Just for sure my html:
{% for i in lista %}
<tr>
<td ><img src="{{i.lojista.imagem}}" class="logo_lojista"> </td>
<td> {{i.nome}}</td>
<td><a class="btn btn-outline-danger btn-sm btn-block td_cupom" href="{% url 'liberar_form' i.id %}" >Liberar Cupom</a></td>
{%if venda != i.cupom %}
<td class="td_status"> {{i.status}}</td>
{%else%}
<td class="td_status">Usado</td>
{%endif%}
<td class="td_desconto"> {{i.desconto}}</td>
<td class="td_estoque"> {{i.estoque}}</td>
</tr>
{% endfor %}
Using the code below I've got the result of a queryset with a list with my Order numbers, now I want to extract the cupom (coupon) field from the Product (FK). Can someone help me ?
#login_required(login_url='login')
def cupons(request):
produtos = Produto.objects.all()
cliente = Cliente.objects.get(user=request.user)
pedido = Pedido.objects.all().filter(cliente=cliente)
return render(request, 'cupons.html', {'lista': produtos, 'venda': pedido})
Result from the filter: <QuerySet [<Pedido: Pedido: 1>, <Pedido: Pedido: 2>]>
Instead of retrieving the order (pedido) records, you can retrieve the products (produtos) of the client (cliente), or even the coupons (cupoms) of the products (produtos) that belongs to the client (cliente). To do that, you can use values_list as follows:
cupoms_usado = Pedido.objects.filter(cliente=cliente).values_list("produto__cupom", flat=True)
It will join two tables (Pedido & Produto) and give you the list of coupons that are used by the client. Then you can simply check if the coupon of the list is in the list of used coupons.
{% if i.cupom in cupoms_usado %}
Note: Do not forget to pass cupoms_usado to your template from the related view.
I have been stucked on this for a couple of days, all help would be really cherished.
I have a list and detail view which are function based views, my detail view works perfectly because i am able to pass the "/str:pk/" at the end of the url and also with the request as(def po_detail(request, pk)) which in turn i am able to pass into my view functions and they all successfully return the unique id i desire.
I have a custom queryset i have written to help me get the sum total amount of some payments and return it in both the list and detail view.
The issues now is that i am not able to get each unique items in my list view page because i am not able to pass the pk into the url and the request function as the object i used it for in detail function has access to the pk.
I have id=True so as to prevent error, because when i made id=id, it gave me a error saying, "Field 'id' expected a number but got ."
The image is pictorial representation of the list template which output both the payment amount and the balance of only the first id instead of the individual id as opposed in the detail template.
This is the image of the detail template which works well as well as for other id
I would love if any one can provide an hint, suggestion, or solution.
Thanks,
Oyero H.O
Below is my model
class PurchaseOrder(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
po_type = models.ForeignKey(PurchaseOrderType, on_delete=models.SET_NULL, null=True)
status = models.CharField(choices=STATUS, max_length=15)
supplier_ID = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True)
order_date = models.DateField()
desired_ship_date = models.DateField()
ready_date = models.DateField()
po_amount = models.IntegerField()
def __str__(self):
return str(self.id)
class PurchaseOrderPayment(models.Model):
po_number = models.ForeignKey(PurchaseOrder, on_delete=models.SET_NULL, null=True)
date = models.DateField()
amount = models.IntegerField()
memo = models.CharField(max_length=200)
def __str__(self):
return self.memo
Below is my view function
#login_required(redirect_field_name='po_list')
def po_list(request):
po_lists = PurchaseOrder.objects.all()
po_detail = PurchaseOrder.objects.get(id=True)
payment_lists_doc = PurchaseOrderPayment.objects.filter(po_number__id=True)
amount = po_detail.po_amount
paid_amount = PurchaseOrderPayment.objects.filter(po_number=po_detail).aggregate(Sum('amount'))['amount__sum']
balance = amount - paid_amount
context = {'po_lists':po_lists, 'payment_lists_doc':payment_lists_doc,
'amount':amount, 'paid_amount':paid_amount, 'balance':balance,
'payment_lists_doc':payment_lists_doc
}
return render(request, 'dashboard/po_list.html', context)
#login_required(redirect_field_name='po_detail')
def po_detail(request, pk):
po_detail = PurchaseOrder.objects.get(id=pk)
payment_lists_doc = PurchaseOrderPayment.objects.filter(po_number__id=pk)
document_lists_doc = PurchaseOrderDocument.objects.filter(po_number__id=pk)
amount = po_detail.po_amount
paid_amount = PurchaseOrderPayment.objects.filter(po_number=po_detail).aggregate(Sum('amount'))['amount__sum']
balance = amount - paid_amount
context = {'po_detail':po_detail, 'payment_lists_doc':payment_lists_doc,
'payment_form':payment_form, 'document_form':document_form,
'document_lists_doc':document_lists_doc,
'paid_amount':paid_amount,
'balance':balance, 'amount':amount}
return render(request, 'dashboard/po_detail.html', context)
This is my list template
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>CREATED</th>
<th>TYPE</th>
<th>STATUS</th>
<th>SUPPLIER NAME</th>
<th>ORDER DATE</th>
<th>AMOUNT</th>
<th>PAID AMOUNT</th>
<th>BALANCE AMOUNT</th>
</tr>
</thead>
<tbody>
{% for po_list in po_lists %}
<tr>
<td style="cursor: pointer;">{{po_list.id}}</td>
<td>{{po_list.created_on}}</td>
<td>{{po_list.po_type}}</td>
<td>{{po_list.status}}</td>
<td>{{po_list.supplier_ID}}</td>
<td>{{po_list.order_date}}</td>
<td>{{po_list.po_amount}}</td>
<td data-toggle="modal" data-target="#paid_amount_modal" style="cursor: pointer;">
{{paid_amount}}
</td>
<td>{{balance}}</td>
</tr>
{% endfor %}
</tbody>
</table>
And lastly, my detail template
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>CREATED</th>
<th>TYPE</th>
<th>STATUS</th>
<th>SUPPLIER NAME</th>
<th>ORDER DATE</th>
<th>AMOUNT</th>
<th>PAID AMOUNT</th>
<th>BALANCE AMOUNT</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{po_detail.id}}</td>
<td>{{po_detail.created_on}}</td>
<td>{{po_detail.po_type}}</td>
<td>{{po_detail.status}}</td>
<td>{{po_detail.supplier_ID}}</td>
<td>{{po_detail.order_date}}</td>
<td>{{po_detail.po_amount}}</td>
<td>{{paid_amount}}</td>
<td>{{balance}}</td>
</tr>
</tbody>
<div></div>
</table>
This is how to do it,
screenshot included,
mark my answer if that helped.
Edit your models.py
class PurchaseOrder(models.Model):
...
#property
def get_payments_sum(self):
return sum(item.get_amount for item in self.items.all())
#property
def get_balance(self):
return self.get_payments_sum - self.po_amount
class PurchaseOrderPayment(models.Model):
po_number = models.ForeignKey(PurchaseOrder, on_delete=models.SET_NULL, null=True, related_name="items")
...
#property
def get_amount(self):
return self.amount
views.py
note that i only edited as to fix your issue (sum and balance), so you have to add whatever else remaining in context like "payment_lists_doc"
def po_list(request):
po_lists = PurchaseOrder.objects.all()
context = {'po_lists':po_lists}
return render(request, 'dashboard/po_list.html', context)
po_lists.html
<tbody>
{% for po_list in po_lists %}
<tr>
<td style="cursor: pointer;">{{po_list.id}}</td>
<td>{{po_list.created_on}}</td>
<td>{{po_list.po_type}}</td>
<td>{{po_list.status}}</td>
<td>{{po_list.order_date}}</td>
<td>{{po_list.po_amount}}</td>
<td data-toggle="modal" data-target="#paid_amount_modal" style="cursor: pointer;">
{{po_list.get_payments_sum}}
</td>
<td>{{po_list.get_balance}}</td>
</tr>
{% endfor %}
</tbody>
enter image description here
First, fix your error
po_detail = PurchaseOrder.objects.get(id=True)
payment_lists_doc =
PurchaseOrderPayment.objects.filter(po_number__id=True)
amount = po_detail.po_amount = True
You need to pass an id (integer) to these fields
I have two models;
class Customer(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
email = models.EmailField()
class WorkOrder(models.Model):
date_created = models.DateField('Date', default=datetime.now)
due_date = models.DateField('Due Date')
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name='Customer')
STATUS_CHOICES = [
('pending', 'Pending'),
('approved', 'Approved'),
('completed', 'Completed'),
('cancelled', 'Cancelled'),
]
status = models.CharField('Status of the work order', max_length=10, choices=STATUS_CHOICES, default='pending')
description = models.TextField('Description of the work')
I wrote a class based list view to make a customer list:
class ReportCustomerListView(ListView):
model = CustomUser
template_name = 'reports/customer_report.html'
def get_queryset(self):
return CustomUser.objects.filter(is_staff=False).filter(is_superuser=False)
I would like to prepare a report for the user about its customers so I wanted to show how many pending, approved and completed work orders a customer have. My list template is;
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Company</th>
<th scope="col">Pending Work Orders</th>
<th scope="col">Active Work Orders</th>
<th scope="col">Completed Work Orders</th>
<th scope="col">Draft Bills</th>
</tr>
</thead>
<tbody>
{% for customer in object_list %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ customer.first_name }}</td>
<td>{{ customer.last_name }}</td>
<td>{{ customer.company.company_name }}</td>
...
...
... // the part where I am stuck
But I am lost after that after 4 hours of reading I am more confused. I know I can access work orders from
>>> Users.objects.get(pk=pk).workorder_set
My question is how can I get the customers work orders counts on each status types on the template? In other words how can I filter the related fields on the objects list on template?
Other methods such as filtering on views would also work for me but again I don't know how to do it.
Thank you very much for your time...
if you want to get your related objects then you should try this django-taggit install in your app and try this code...
views.py
def tagged(request, slug):
tag = get_object_or_404(Tag, slug=slug)
# Filter posts by tag name
posts = Post.objects.filter(tags=tag)
context = {
'tag':tag,
'posts':posts,
}
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.
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