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

Надеюсь, это правильный путь. Теперь у меня есть то, что я искал. Спасибо за советы, которые вы мне дали.

Вернуться на верх