I have 3 models:
class Chemicals(models.Model):
id_chemical = models.AutoField(primary_key=True)
id_supplier = models.ForeignKey(Suppliers, null=True, on_delete = models.CASCADE)
description = models.CharField(max_length=50, blank=False, null=False)
[...]
class Suppliers(models.Model):
id_supplier = models.AutoField(primary_key=True)
company_name = models.CharField(max_length=100, blank=False, null=False)
[...]
class Prices(models.Model):
id_chemical=models.ForeignKey(Chemicals, null=False, on_delete = models.CASCADE, related_name='prezzo')
price=models.IntegerField(blank=False, null=False, default=0)
price_date=models.DateField(default=datetime.date.today)
I need to get the latest price by date and use it in a queryset to show it in a template. I tried this solution:
def price_list(request,pk):
supplier = get_object_or_404(Suppliers, pk=pk)
chemicals_list = Chemicals.objects.filter(id_supplier=pk)
chem_price = chemicals_list
qs = Prices.objects.all()
prova = qs.values('id_chemical').annotate(latest_price=Max('price_date'))
qs = qs.filter(price_date__in=prova.values('latest_price').order_by('- price_date')).filter(id_chemical__id_supplier=pk)
context = {'supplier': supplier, 'chemicals_list': chemicals_list, 'qs': qs, 'chem_price': chem_price}
return render(request, "chemicals/price_list.html", context)
Now I have what I need but if I want to show it in a template I have some problem. I tried to do this:
<tbody>
{% for chemical in chem_price %}
<tr>
<td><a href="{% url 'chemicals:single-product' pk=chemical.id_chemical %}">{{ chemical.description }}</a></td>
<td>{{ qs.price }}</td>
<td>{{ chemical.cov }}</td>
{% endfor %}
</tbody>
Whit this solution, in template I see the same price for all products. I need to take some columns of my chemicals model, add latest price and show in a table row in a template.
CodePudding user response:
There are multiple points which I noticed that may need to be considered for better understanding of your code to yourself and potentially help you solve your problem as well.
Class names should not be in plural form, as a class definition indicates a single entity (instance) of itself. So instead of
, useclass Chemicalsclass Chemical, and similarly everywhere.The
id_chemicalattribute that you intend to use as primary key of yourclass Chemicals, can be simply named asid, as the attribute itself is inside Chemicals class, therefore we don't need to mention it in its attribute name too. Similarly for other non-relation attributes.The
id_supplierattribute that you intend to use as foreign key of yourclass Chemicalsfor relation withclass Suppliers, can be simply named assupplier, as when you'll access this foreign key for an instance of Chemical, the attribute can be used to access the attributes of the related Supplier instance. So, for instance, instead of looking like the followingchemical = Chemicals.objects.get(id=pk) return chemical.id_supplier.company_nameit will look better and will be more understandable like following
chemical = Chemical.objects.get(id=pk) return chemical.supplier.company_name
Similarly, there can be other improvements which will make your code more readable and understandable to everyone, and especially to you.
Now coming to your actual problem. Considering the recommendations in the aforementioned points and assuming that I've understood your problem correctly, your html code may need the following changes to work properly
- You're not closing your
<tr>tag. - There's no
chem_priceobject defined anywhere - The
chemicalobject that you're using inforloop is actually aclass Priceobject, so can't use{{chemical.description}}directly.
Other factors, like improper context data can also affect your desired outcome.
CodePudding user response:
I found a possible solution. In my Chemicals model, I put a method to get the last price
class Chemicals(models.Model):
[...]
def get_price(self):
price_object = Prices.objects.all()
partial_qs=price_object.values('id_chemical').annotate(latest_price=Max('price_date'))
price_object=price_object.filter(price_date__in=partial_qs.values('latest_price').order_by('-price_date')).get(id_chemical=self.id_chemical)
price = price_object.price
return price
Then, in my template:
{% for chemical in chemicals_list %}
<tr>
<td><a href="{% url 'chemicals:single-product' pk=chemical.id_chemical %}">{{ chemical.description }}</a></td>
<td>{{ chemical.get_price }}</td>
<td>{{ chemical.cov }}</td>
</tr>
{% endfor %}
I hope this may be the right way. Now I have what I was searching for. Thanks for the suggestions you gave me.
