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

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

Related

Django Queryset to include and filter related data

I'm trying to render a template with a list of participants (adult and minor) and their latest checkin and checkout times.
There are two types of participants and they are represented in two tables/models: AdultParticipant and MinorParticipant. MinorParticipants have a foreign key relationship to the ParentParticipant.
Checkin information (checkin and checkout) is stored in a single table irregardless of whether the checkin data refers to AdultParticipant or the MinorParticipant. One record in this table captures the participant reference and the checkin and checkout times.
Any participant can have many checkins. A checkin record can only have one participant.
The code as it exists now does everything I want except it displays every checkin record for the participant. I only want to display the last (most recent) record for the participant.
How can I construct the queryset to include the participant information and include only the last checkin record for the participant?
Thank you in advance. You are appreciated.
Models
class AdultParticipant(models.Model):
first_name = models.CharField(max_length=50)
middle_initial = models.CharField(max_length=50, blank=True)
class MinorParticipant(models.Model):
first_name = models.CharField(max_length=50)
middle_initial = models.CharField(max_length=50, blank=True)
parent = models.ForeignKey(
WaiverAdult, on_delete=models.CASCADE, related_name='minor_of_adult')
class CheckIn(models.Model):
adult = models.ForeignKey(
AdultParticipant, on_delete=models.CASCADE, blank=True, null=True, related_name='adult_checkin')
minor = models.ForeignKey(
MinorParticipant, on_delete=models.CASCADE, blank=True, null=True, related_name='minor_checkin')
checkin = models.DateTimeField(blank=True, null=True)
checkout = models.DateTimeField(blank=True, null=True)
View
class WaiverListView(ListView):
participants_and_checkins = AdultParticipant.objects.all().order_by('created')
queryset = participants_and_checkins
context_object_name = "the_list"
template_name = 'list.html'
Template
{% for adult in the_list %}
<tr>
<td class="fs-6">
{% for c in adult.adult_checkin.all|dictsortreversed:"checkin" %}
In: {{ c.checkin }}</br>
Out: {{c.checkout}}</br>
{% endfor %}
</td>
<td>{{adult.last_name}}</td>
<td>{{adult.first_name}}</td>
</tr>
{% for child in adult.minor_of_adult.all %}
<tr>
<td class="fs-6">
{% for c in child.minor_checkin.all|dictsortreversed:"checkin" %}
In: {{ c.checkin }}</br>
Out: {{c.checkout}}
{% endfor %}
</td>
<td>{{child.last_name}}</td>
<td>{{child.first_name}}</td>
</tr>
{% endfor %}
{% endfor %}
in your template change checkin.all to checkin.last.
Also you can get rid of the for loop as well,like
In: {{ child.minor_checkin.last.checkin }}</br>
Out: {{child.minor_checkin.last.checkout}}

Print all attributes from an object with Django templates

I am a novice programmer, I am learning python and Django on my own. I got stuck in a part of my application:
I have many models with many attributes, and I have a window and a template for each of them.
The idea is to show in each one, a table with all its content with an sql query in the file view.py
objects.all ()
My code:
MODELS.PY
from django.db import models
class MFuel(models.Model):
marca = models.TextField(db_column='Marca', blank=True, null=True) # Field name made lowercase.
modelo = models.TextField(db_column='Modelo', blank=True, null=True) # Field name made lowercase.
potencia_electrica_kw = models.BigIntegerField(db_column='Potencia_electrica_kW', blank=True, null=True) # Field name made lowercase.
fecha_oferta = models.DateTimeField(db_column='Fecha_oferta', blank=True, null=True) # Field name made lowercase.
pais_proyecto = models.TextField(db_column='Pais_Proyecto', blank=True, null=True) # Field name made lowercase.
proyecto = models.TextField(db_column='Proyecto', blank=True, null=True) # Field name made lowercase.
uds = models.FloatField(db_column='Uds', blank=True, null=True) # Field name made lowercase.
precio_eur = models.FloatField(db_column='Precio_EUR', blank=True, null=True) # Field name made lowercase.
precio_usd = models.FloatField(db_column='Precio_USD', blank=True, null=True) # Field name made lowercase.
precio_unitario_eur = models.FloatField(db_column='Precio_Unitario_EUR', blank=True, null=True) # Field name made lowercase.
ratio_eur_kw = models.FloatField(db_column='Ratio_eur_KW', blank=True, null=True) # Field name made lowercase.
largo_mm = models.FloatField(db_column='Largo_mm', blank=True, null=True) # Field name made lowercase.
ancho_mm = models.FloatField(db_column='Ancho_mm', blank=True, null=True) # Field name made lowercase.
alto_mm = models.FloatField(db_column='Alto_mm', blank=True, null=True) # Field name made lowercase.
peso_kg = models.FloatField(db_column='Peso_kg', blank=True, null=True) # Field name made lowercase.
presupuesto = models.TextField(db_column='Presupuesto', blank=True, null=True) # Field name made lowercase.
esp_tecnicas = models.TextField(db_column='Esp_Tecnicas', blank=True, null=True) # Field name made lowercase.
observaciones = models.FloatField(db_column='OBSERVACIONES', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'm_fuel'
VIEWS.PY
def m_fuel(request):
fuel = MFuel.objects.all()
# QuerySet
myFilter = Filter(request.GET, queryset=fuel)
fuel = myFilter.qs
total = fuel.count()
attr = MFuel.__doc__
inici = attr.index("(") + 1
fi = attr.index(")")
nom_columnes = attr[inici:fi]
nom_columnes = str(nom_columnes)
nom_columnes = nom_columnes.split(",")
dict = {
"fuel": fuel,
"filter": myFilter,
"motores": motores_list,
"total": total,
"nom_columnes": nom_columnes,
}
return render(request, "motores/fuel.html", dict)
TEMPLATE.HTML
<table class="table_info">
<tr>
{% for nom in nom_columnes %}
<th>{{nom}}</th>
{% endfor %}
</tr>
{% for i in fuel %}
<tr>
<td>{{i.id}}</td>
<td>{{i.marca}}</td>
<td>{{i.modelo}}</td>
<td>{{i.potencia_electrica_kw}}</td>
<td>{{i.fecha_oferta}}</td>
<td>{{i.pais_proyecto}}</td>
<td>{{i.proyecto}}</td>
<td>{{i.uds}}</td>
<td>{{i.precio_eur}}</td>
<td>{{i.largo_mm}}</td>
<td>{{i.ancho_mm}}</td>
<td>{{i.alto_mm}}</td>
<td>{{i.peso_kg}}</td>
<td>{{i.presupuesto}}</td>
</tr>
{% endfor %}
</table>
My idea is to automate the table columns by accessing all the attributes of the class.
I tried pulling out a list of the attribute names
attr = MFuel .__ doc__
and print them as follows:
<table class="table_info">
<tr>
{% for nom in nom_columnes %}
<th>{{nom}}</th>
{% endfor %}
</tr>
{% for i in fuel %}
<tr>
{% for nom in nom_columnes %}
<td>{{i.nom}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
but this shows nothing:
capture that this code shows
It seems that it does not recognize the name as an attribute of the class, it must be because it is a string?
I saw this question, but I don't understand it
Django - print all objects attribute values
Any help to automate this? Thanks a lot
I have been able to solve my problem, I share it in case someone needs it
This returns a list of all the values available:
fuel = fuel.values()
and print them:
<table class="table_info">
<tr>
{% for nom in nom_columnes %}
<th>{{nom}}</th>
{% endfor %}
</tr>
{% for i in fuel %}
<tr>
{% for key, value in i.items %}
<td>{{value}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
And all ok

Django: loop all the records in a table and then get field from another table

I got two class models called Buy and Sell:
class Buy(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
image = models.FileField()
date = models.DateField()
buy_price = models.DecimalField(max_digits=6, decimal_places=2)
sell_price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.id)
class Sell(models.Model):
item = models.OneToOneField(Buy, on_delete=models.CASCADE)
date = models.DateField()
discount = models.DecimalField(max_digits=6, decimal_places=2)
total_paid = models.DecimalField(max_digits=6, decimal_places=2)
buyer = models.ForeignKey(Buyer, on_delete=models.CASCADE)
def __str__(self):
return str(self.item)
In a template, I'd like to display all the records from the Sell table and also the image class-attribute from Buy table.
Below, my view.py:
def sell(request):
buys = []
sells = Sell.objects.order_by('-id')
for sell in sells:
buys.append(Buy.objects.filter(id=str(sell.item)))
context = {'sells': sells, 'buys': buys}
return render(request, 'sell.html', context)
Template:
{% for sell in sells %}
<tr>
<td>{{ sell.item }}</td>
<td>{{ sell.date|date:'d-m-Y' }}</td>
<td>{{ buys[0].image}}</td>
<td>R$ {{ sell.discount }}</td>
<td>R$ {{ sell.total_paid }}</td>
<td>{{ sell.buyer }}</td>
</tr>
{% endfor %}
I'm wondering if there is a simple way to do that. I need some help in my view.py!
You can access the Buy entity related to the Sell inside the template
{{sell.item.image}}
If the image field is as the name suggests a image you might want to change the field to a ImageField.
Then the code to display the image would be:
<img src="{{ sell.item.image.url }}">
(found here)

Django: Sum Total value over Foreign Key Data

I am using Django 1.11 and Python3.5
I have created a table. This is a screenshot.
When I got a table from my query database, it is showing 10+2+3... but I want to get total sum value for every customer within Due Taka update column in table like this 10+2+4+2 = 18
this is my model.py file
class CustomerInfo(models.Model):
customer_name = models.CharField('Customer Name', max_length=100)
customer_mobile_no = models.CharField(
'Mobile No', null=True, blank=True, max_length=12)
customer_price=models.IntegerField('Customer Price',default=1)
customer_product_warrenty = models.CharField('Product Warrenty',null=True, blank=True,max_length=10)
customer_sell_date = models.DateTimeField('date-published', auto_now_add=True)
customer_product_id=models.CharField('Product ID',max_length=300,null=True, blank=True)
customer_product_name=models.TextField('Product Name')
customer_product_quantity=models.IntegerField('Quantity',default=1)
customer_uid = models.CharField(max_length=6, blank=True, null=True)
customer_info=models.TextField('Customer Details Informations', blank=True, null=True)
customer_conditions=models.CharField('Conditions',blank=True, null=True, max_length=300)
customer_due_taka_info=models.IntegerField(default=0)
customer_discount_taka=models.IntegerField(default=0)
customer_first_time_payment=models.IntegerField('First Time Payment',default=0)
customer_first_due_info = models.CharField('First Due Info',default='No due info', max_length=200, blank=True, null=True)
customer_product_mrp=models.IntegerField('Products MRP', default=0)
customers_refrence=models.CharField(max_length=100)
customer_updated = models.DateTimeField(auto_now=True)
customer_type=models.CharField('Customer Type', default='MobilePhone', max_length=50)
def __str__(self):
return self.customer_name
def remainBalance(self):
if self.customer_price > self.customer_due_taka_info:
remain=self.customer_price - self.customer_due_taka_info
return remain
def totalRetalsPerSingle(self):
return self.customer_product_quantity * self.customer_product_mrp
#def product_warrenty(self):
#expire_date_oneyr =self.customer_sell_date+ datetime.timedelta(days=365)
#return 'This product expire on this date ' + str(expire_date_oneyr)
class Meta:
verbose_name = ("গ্রাহকের তথ্য")
verbose_name_plural = ("গ্রাহকের তথ্যসমূহ")
#intregated with Customerinfo Model (Using foreignKey)
class DueTaka(models.Model):
customer_due = models.IntegerField('Due Taka', default=0)
customer_due_date=models.DateTimeField(auto_now_add=True)
customer_due_info=models.CharField('Due Info', max_length=200, blank=True, null=True)
customerinfo = models.ForeignKey(CustomerInfo, on_delete=models.CASCADE)
due_customer_updated = models.DateTimeField(auto_now=True)
def __int__(self):
return self.customer_due
def sum_total(self):
return self.customer_due
this is my views.py file
due_update_info = CustomerInfo.objects.filter(duetaka__customer_due_date__range=(starts_date, tomorrow)).order_by('-customer_updated')
I want to get total price customer_due fields within DueTaka model for per single customer. if a customer name is 'asad'. He has some multple due taka and he paid multiple times like this 10+20+20 Now I want to get total value like 50
If I update my customer's profile, same customers name come again with in loop my table. But I don't want this.
and this is my html template file
<h1>Due Paid Book</h1>
<table class="table table-hover table-bordered">
<p style="font-size:16px;">Due Paid Tody</p>
<thead>
<tr>
<th>No</th>
<th>Name</th>
<th>Invoice ID</th>
<th>Mobile</th>
<th>Product</th>
<th>Product MRP</th>
<th>Customer Paid (TK)</th>
<th>Due Amount</th>
<th>Total Price</th>
<th>Warrenty</th>
<th>Purchase Date</th>
<th>Due Taka update</th>
<th>Update Date</th>
<th>QN</th>
</tr>
</thead>
{% for x in due_update_info %}
<tbody>
<tr>
.......code in here.......
<td>
{% for y in x.duetaka_set.all %}
{{y.customer_due | intcomma}}+
{% endfor %}
{{x.duetaka_set }}
<!--i want to toatal value in here, now nothing showing-->
{{total_price}}
</td>
</tr>
<tr>
</tr>
</tbody>
{% endfor %}
<td colspan="10"></td>
<td> Total Du Paid <br> <i>{{starts_date}} to {{end_date}}</i> </td>
<td> <b>{{dupaid_today|intcomma}} TK</b> </td>
</table>
Now How can I implement in views file?
Maybe change the filter query like this this:
CustomerInfo.objects.filter(duetaka__customer_due_date__range=(starts_date, tomorrow)).annotate(due_taka_total=Sum('duetaka__customer_due')).order_by('-customer_updated')
which will give you additional field 'due_taka_total', which can be used in template, like:
{{ y.due_taka_total }}
assuming y is an object of CustomerInfo
OR
You could write a custom template tag and find out the total using it:
from django import template
register = template.Library()
#register.simple_tag
def get_total_taka(customer_info_object):
return sum([each.customer_due for each in customer_info_object.duetaka_set.all()])
and use it in template like this:
{% get_total_taka y %}
assuming y is an object of Customerinfo
For writing the custom template tag refer: Writing Custom Tags

Django prefetch_related outputs None

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

Categories