да именно такие делал. Ничего не обычного, разве что с запросом пришлось помучаться. Может чем то поможет, удачи:)
class Category(MPTTModel):
title = models.CharField(max_length=255, verbose_name=_(u'Название'))
feature_category = models.ManyToManyField('FeatureCategory', verbose_name=_(u'Характеристики'), blank=True, null=True)
class Brand(models.Model):
title = models.CharField(max_length=255, verbose_name=_(u'Название'))
class Product(models.Model):
title = models.CharField(max_length=255, verbose_name=_(u'Название'))
category = models.ForeignKey('Category', verbose_name=_(u'Категория'))
brand = models.ForeignKey('Brand', verbose_name=_(u'Бренд'))
class ProductFeature(models.Model):
product = models.ForeignKey('Product')
feature_category = models.ForeignKey('FeatureCategory')
feature = models.ForeignKey('Feature')
filter_key = models.CharField(max_length=255, blank=True)
class FeatureCategory(models.Model):
title = models.CharField(max_length=255, verbose_name=_(u'Название'))
icon = models.ImageField(upload_to='images/', verbose_name=_(u'Иконка'), blank=True, null=True)
class Feature(models.Model):
category = models.ForeignKey('FeatureCategory')
title = models.CharField(max_length=255, verbose_name=_(u'Значение'))
class ProductListView(ListView):
model = Product
context_object_name = 'products'
def get_template_names(self):
view = self.request.GET.get('view', 'tile')
if view == 'tile':
self.template_name = "catalog/product_list_tiles.html"
else:
self.template_name = "catalog/product_list_linear.html"
return self.template_name
def get_queryset(self):
order = self.request.GET.get('order', 'order')
pagination = self.request.GET.get('pangination', 24)
filters = []
for param in self.request.GET:
if not param in ['pangination', 'view', 'order', 'page']:
filters.append(param)
category = get_object_or_404(Category, slug=self.kwargs['slug'])
descendants = category.get_descendants(include_self=True)
if filters:
filter_str = ', '.join(["'%s'" % x for x in filters])
descendants_str = ', '.join(["'%s'" % descendant.pk for descendant in descendants])
if order.startswith("-"):
order_str = 'cp.%s DESC' % order[1:]
else:
order_str = 'cp.%s' % order
self.queryset = Product.objects.raw("SELECT * FROM catalog_product cp "
"LEFT JOIN catalog_productfeature cpf ON (cp.id=cpf.product_id) "
"WHERE cpf.filter_key IN (%s) AND cp.category_id IN (%s)"
"GROUP BY cp.id HAVING COUNT(cpf.filter_key)=%s ORDER BY %s" % (filter_str, descendants_str, len(filters), order_str))
self.queryset = list(self.queryset)
else:
self.queryset = Product.objects.filter(
category__in=descendants,
is_hidden=False,
).order_by(order)
try:
page = int(self.request.GET.get('page', 1))
self.queryset = Paginator(self.queryset, pagination).page(page)
except ValueError:
self.queryset = Paginator(self.queryset, pagination).page(1)
except EmptyPage:
pass
return self.queryset