Django - получить последнюю цену для каждого продукта и поместить в набор запросов для отображения в шаблоне
У меня есть 3 модели:
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)
Мне нужно получить последнюю цену по дате и использовать ее в наборе запросов, чтобы показать ее в шаблоне. Я попробовал следующее решение:
def price_list(request,pk):
supplier = get_object_or_404(Suppliers, pk=pk)
chemicals_list = Chemicals.objects.filter(id_supplier=pk)
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)
Теперь у меня есть то, что мне нужно, но если я хочу показать это в шаблоне, у меня возникает проблема. Я пытался сделать следующее:
<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>
После этого решения, в шаблоне я вижу одну и ту же цену для всех продуктов. Мне нужно взять несколько колонок из моей модели химикатов, добавить последнюю цену и показать в строке таблицы в шаблоне.
Есть несколько моментов, которые я заметил, которые, возможно, следует рассмотреть для лучшего понимания вашего кода для себя и потенциально помочь вам решить вашу проблему, а также.
Имена классов не должны быть в форме множественного числа, так как определение класса указывает на единственную сущность (экземпляр) самого себя. Поэтому вместо
используйтеclass Chemicals
class Chemical
, и аналогично везде.Атрибут
id_chemical
, который вы собираетесь использовать как первичный ключ вашегоclass Chemicals
, можно назвать простоid
, так как сам атрибут находится внутри класса Chemicals, поэтому нам не нужно упоминать его в имени атрибута. Аналогично для других атрибутов, не связанных с отношениями.Атрибут
id_supplier
, который вы собираетесь использовать в качестве внешнего ключа вашегоclass Chemicals
для связи сclass Suppliers
, можно назвать простоsupplier
, так как когда вы будете обращаться к этому внешнему ключу для экземпляра Chemical, атрибут может быть использован для доступа к атрибутам связанного экземпляра Supplier. Так, например, вместо того, чтобы выглядеть следующим образомchemical = Chemicals.objects.get(id=pk) return chemical.id_supplier.company_name
он будет выглядеть лучше и будет более понятным следующим образом
chemical = Chemical.objects.get(id=pk) return chemical.supplier.company_name
Точно так же могут быть и другие улучшения, которые сделают ваш код более читаемым и понятным для всех, и особенно для вас.
Теперь перейдем к вашей проблеме. Учитывая рекомендации в вышеупомянутых пунктах и предполагая, что я правильно понял вашу проблему, вашему html-коду могут потребоваться следующие изменения для корректной работы
- Вы не закрываете тег
<tr>
. - Нигде не определен объект
chem_price
. Объект - , который вы используете в цикле
chemical
, на самом деле является объектомfor
, поэтому нельзя использоватьclass Price
напрямую.{{chemical.description}}
Другие факторы, такие как неправильные контекстные данные, также могут повлиять на желаемый результат.
Я нашел возможное решение. В моей модели Chemicals я поместил метод для получения последней цены
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
Затем, в моем шаблоне:
{% 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 %}
Надеюсь, это правильный путь. Теперь у меня есть то, что я искал. Спасибо за советы, которые вы мне дали.