Доброго времени суток. Пишу магазин на Джанго, опыта немного, до этого была только пара несложных сайтов. Столкнулся с проблемой при реализации фильтра в каталоге. Имеется вот такая модель данных:
class Category(MPTTModel):
name = models.CharField(max_length=100, verbose_name=u'Название категории', unique=True)
slug = models.SlugField(max_length=100, verbose_name=u'Адрес категории', unique=True)
description = models.TextField(verbose_name=u'Описание категории')
is_active = models.BooleanField(default=True, verbose_name=u'Активная категория')
meta_keywords = models.CharField(max_length=255, verbose_name=u'Ключевые слова')
meta_description = models.CharField(max_length=255, verbose_name=u'Мета описание')
created_at = models.DateTimeField(auto_now_add=True, verbose_name=u'Создана')
updated_at = models.DateTimeField(auto_now=True, verbose_name=u'Обновлена')
parent = TreeForeignKey('self', verbose_name=u'Родительская категория',
related_name='children', blank=True, null=True)
class Meta:
db_table = 'category'
ordering = ['name']
verbose_name = u'Категория'
verbose_name_plural = u'Категории'
def __unicode__(self):
return self.name
class BrandDevice(models.Model):
name = models.CharField(max_length=30, verbose_name=u'Производитель')
class Meta:
db_table = 'branddevice'
ordering = ['name']
verbose_name = u'Производитель устройств'
verbose_name_plural = u'Производители устройств'
def __unicode__(self):
return self.name
class Device(models.Model):
brand = models.ForeignKey(BrandDevice, verbose_name=u'Производитель устройства')
name = models.CharField(max_length=100, verbose_name=u'Модель устройства')
class Meta:
db_table = 'device'
ordering = ['name']
verbose_name = u'Устройство'
verbose_name_plural = u'Устройства'
def __unicode__(self):
return '%s %s' % (self.brand, self.name)
class ProductType(models.Model):
name = models.CharField(max_length=100, verbose_name=u'Тип аксессуара')
class Meta:
db_table = 'producttype'
ordering = ['name']
verbose_name = u'Тип аксессуара'
verbose_name_plural = u'Типы аксессуаров'
def __unicode__(self):
return self.name
class Product(models.Model):
type = models.ForeignKey(ProductType, verbose_name=u'Тип аксессуара')
name = models.CharField(max_length=100, verbose_name=u'Название товара', unique=True)
slug = models.SlugField(max_length=100, verbose_name=u'URL товара', unique=True)
price = models.DecimalField(default=0, max_digits=9, decimal_places=2, verbose_name=u'Цена')
is_active = models.BooleanField(default=True, verbose_name=u'Активный товар')
is_color = models.BooleanField(default=False, verbose_name=u'Несколько цветов')
meta_keywords = models.CharField(max_length=255, verbose_name=u'Ключевые слова')
meta_description = models.CharField(max_length=255, verbose_name=u'Мета описание')
description = models.TextField(verbose_name=u'Описание')
categories = models.ManyToManyField(Category, verbose_name=u'Категории')
devices = models.ManyToManyField(Device, verbose_name=u'Совместимые устройства')
created_at = models.DateTimeField(auto_now_add=True, verbose_name=u'Дата создания')
updated_at = models.DateTimeField(auto_now=True, verbose_name=u'Дата обновления')
class Meta:
db_table = 'product'
ordering = ['name']
verbose_name = u'Товар'
verbose_name_plural = u'Товары'
def __unicode__(self):
return self.name
class Color(models.Model):
name = models.CharField(max_length=20, verbose_name=u'Имя цвета')
color = models.CharField(max_length=7, verbose_name=u'Цвет')
class Meta:
db_table = 'color'
verbose_name = u'Цвет'
verbose_name_plural = u'Цвета'
def __unicode__(self):
return self.name
class Image(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to='img/product', verbose_name=u'Картинка')
color = models.ForeignKey(Color, blank=True, null=True, verbose_name=u'Цвет')
is_main = models.BooleanField(default=False, verbose_name=u'Главная картинка')
class Meta:
verbose_name = u'Картинка'
verbose_name_plural = u'Картинки'
Вот urls.py:
from django.conf.urls import patterns, url
from catalog.views import *
urlpatterns = patterns('',
url(r'^product/(?P<product_slug>[-\w]+)/$', show_product, name='product'),
url(r'^category/(?P<category_slug>[-\w]+)/$', show_category, name='category'),
url(r'^set_device', set_device, name='set_device'),
)
Вот views для категории:
def show_category(request, category_slug):
category = get_object_or_404(Category, slug=category_slug)
name = category.name
description = category.description
meta_keywords = category.meta_keywords
meta_description = category.meta_description
brands = BrandDevice.objects.all()
devices = Device.objects.all()
data = request.COOKIES.copy()
if data.has_key('device'):
dev = data['device']
device = Device.objects.get(name=dev)
products = device.product_set.filter()
else:
products = category.product_set.all()
request.session.set_test_cookie()
return render_to_response('category.html', locals(), context_instance=RequestContext(request))
Собственно проблема. В куки устанавливается устройство для которого пользователь ищет аксессуары. После выбора устройства на всех страницах должны отображаться только совместимые устройства. Но я не совсем понимаю как отфильтровать выборку по полю с типом ManytoMany или ForeignKey. Конкретнее, что именно должно быть аргументом для filter() вот тут:
products = device.product_set.filter()
Я уже читал документацию, но там, как я понял говорится только об обратном случае, когда обычное поле проверяется на вхождение в данный список. К примеру: products = device.product_set.filter(name_in=[name1, name2]). Это самое близкое, что я нашёл.
Прошу знающий людей написать пример, указать на конкретный пункт документации, объяснить, если я где-то ошибся по ходу. Заранее благодарен за любую помощь.