Как реализовать фасетную фильтрацию на Django?

Здравствуйте! Подскажите как лучше реализовать фасетную фильтрацию товаров в магазине.
Все свойства товаров, по которым будет осуществляться фильтрация хранятся в тегах, которые связываются с моделью продукта через ManyToManyField. В разделе каталога выводятся только те теги, которые привязаны к продуктам данной категории, за выбор нужных тегов отвечает такая функция:
class TagFilter(object):
    def __init__(self, category_slug, prop_name):
        self.name = prop_name
        tags = []
        tag_set = Tag.objects.filter(prop=prop_name, products__in=Product.objects.filter(category=category_slug)).values_list('name', flat=True)
        for t in tag_set:
            if t not in tags:
                tags.append(t)
        self.tags = tags

Всё что я дальше смог сделать - это вывести эти теги в шаблон, а с реализацией самой фильтрации встал. Помимо фильтрации по тегам есть ещё фильтрация по производителям, а также вывод товаров по убывающей цене/возрастающей цене - и как реализовать это не могу понять.
Читал про Haystack и ElasticSearch, но не уверен как именно их нужно применить для решения проблемы
Модели:
@python_2_unicode_compatible
class Tag(models.Model):
    PROPS = (
        ('c', 'цвет'),
        ('e', 'эффект'),
    )
    name = models.CharField(_('Tag name'), max_length=30, unique=True)
    prop = models.CharField(_('Tag property'), max_length=30, choices=PROPS)

    def __str__(self):
        return self.name 
    class Meta:
        verbose_name = 'Тег'
        verbose_name_plural = 'Теги'        

@python_2_unicode_compatible
class Product(models.Model):
    UNITS = (
        ('кг', 'кг.'),
        ('гр', 'гр.'),
        ('шт', 'шт.'),
    )
    name = models.CharField(_('Product name'), max_length=60)
    slug = models.SlugField(_('Unique product slug'), max_length=60, unique=True, null=True)
    category = models.ManyToManyField(Category, related_name='products')
    tag = models.ManyToManyField(Tag, related_name='products', blank=True, null=True)
    manufacturer = models.ForeignKey(Manufacturer, related_name='products', 
                                                    blank=True, null=True, on_delete=models.SET_NULL)
    active = models.BooleanField(_('Enable product?'), default=False)
    price = models.IntegerField(_('Price'))
    price_discounted= models.IntegerField(_('Price with discount'), blank=True, null=True)
    description = models.TextField(_('Product description'), max_length=501, blank=True, null=True)
    brief = models.CharField(_('Brief descr for cat. view'), max_length=60)
    netto = models.PositiveIntegerField(_('Netto mass'))
    preview = models.ImageField(_('Product preview image'), upload_to="images")
    unit = models.CharField(_('Unit'), choices=UNITS, max_length=11)
    stock = models.BooleanField(_('Is in stock?'), default=False)

    def get_preview_price(self):
        return self.price * self.netto

#    def get_absolute_url(self):
#        return reverse('teashop:ProductView', args=[self.slug])    

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name',)
        verbose_name = 'Продукт'
        verbose_name_plural = 'Продукты'
        index_together = [
            ['id', 'slug']
        ]
  • Вопрос задан
  • 500 просмотров
Пригласить эксперта
Ваш ответ на вопрос

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

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