Как получить количество продуктов из foreign key django?

У меня есть 2 класса модели и мне нужно получить количество продуктов у каждого из поставщиков

class Vendor(models.Model):
        name = models.CharField(max_length=50, unique=True)
        seo_name = models.SlugField()
        product_count = models.IntegerField(default=0)    
    
    
class Product(models.Model):
            vendor = models.ForeignKey(Vendor, unique=False, blank=True, default=None, null=True, on_delete=models.SET_NULL)



Как это сделать?

Написал вот такой метод в Vendor:
class Vendor(models.Model):
    name = models.CharField(max_length=50, unique=True)
    seo_name = models.SlugField()
    product_count = models.IntegerField(default=0, editable=True)

    def count_products(self):
        count = self.product_set.count()
        self.product_count = count
        self.save()

такой signals.py:
from django.db.models import signals
from django.dispatch import dispatcher

def count_products(sender, instance, signal, *args, **kwargs):

    from products.models import Vendor
    for product_type in Vendor.objects.all():
        product_type.count_products()

В модели где Vendor и Product сигналы такие:
signals.post_save.connect(count_products, sender=Product)
signals.post_delete.connect(count_products, sender=Product)
  • Вопрос задан
  • 2197 просмотров
Решения вопроса 1
@deliro
vendor.product_set.count()

Когда ты создаёшь FK(Vendor) для модели Product, Django создаёт обратную связь (менеджер) для модели Vendor, имя по-умолчанию - имямодели_set. Изменяется переопределением related_name. Например:
class Product(models.Model):
    vendor = models.ForeignKey(Vendor, related_name='products')

При таком коде ты сможешь обращаться к продуктам так:
some_vendor.products.all()
Раз это менеджер, для него доступны все те же действия, что и для стандартного (objects):
some_vendor.products.filter(key=value)
some_vendor.products.create(your=params)  # Создаст продукт с уже заполненым полем vendor=some_vendor


Следует отметить, что если у модели два FK на одну модель, то related_name переопределить придётся, иначе появляется двусмысленность:
class Message(Model):
    sender = ForeignKey(User)
    recipient = ForeignKey(User)
    text = TextField()

При таком коде, если ты хочешь получить, например, сообщения, которые отправил/получил user, совершенно неясно, что нужно писать, поэтому нужно либо отключить обратную связь (related_name='+'), либо предоставить её:
class Message(Model):
    sender = ForeignKey(User, related_name='sent_messages')
    recipient = ForeignKey(User, related_name='received_messages')
    text = TextField()
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы