Получить связи m2m в обратном порядке

Есть две модели, со связью многие ко многим

class ProductCategory(MPTTModel):
    """Категории"""
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255, null=True, blank=True,)
    #parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
    
    class MPTTMeta:
        order_insertion_by = ['name']            
        
    def __str__(self):
        return self.name


class Product(models.Model):    
    """Продукты"""
    name = models.CharField(max_length=1024)     
    category_id = models.ManyToManyField(ProductCategory, related_name="category_product") 

    def __str__(self):
        return self.name

Мне нужно исходя из категории получить все продукты

queryset = Product.objects.prefetch_related('category_id')
stores = []
for store in queryset:
    category = [book.name for book in store.category_id.all()]
    stores.append({'id': store.id, 'name': store.name, 'category': category})
print(stores)

А получается наоборот, получаю все категории продукта:

[{'id': 8, 'name': 'Продукт1', 'category': ['Вкладыши шатунные', 'ГБЦ', 'Буферы']}]

Как из категории получить все продукты?


Ответы (1 шт):

Автор решения: 5c0rp

Можно добавить в ProductCategory метод get_products который вернёт все продукты связанные с конкретной категорией:

class ProductCategory(MPTTModel):
    """Категории"""
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255, null=True, blank=True,)
    #parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')

    class MPTTMeta:
        order_insertion_by = ['name']            
    
    def __str__(self):
        return self.name

    def get_products(self):
        return self.category_product.all()

Ну и по вашему примеру:

categories = ProductCategory.objects.prefetch_related('category_product')
stores = []
for category in categories:
    products = [{'product_id: product.id', 'product_name': product.name} for product in category.get_products()]
    stores.append({'category_id': category.id, 'category_name': category.name, 'products': products})
→ Ссылка