среда, 20 октября 2010 г.

Реализация динамических фильтров в Django

Проблема
Постановка задачи: Есть таблица, с какими-то полями, к примеру такая
class Product(models.Model):
place = models.ManyToManyField(Place) # место расположения продукта
product_type = models.ManyToManyField(ProductType) # тип продукта
producer = models.ManyToManyField(Producer) # производитель


product_name = models.CharField(_(u'product name'), max_length=200) # название продукта
unit = models.CharField(_(u'unit'), max_length=15, blank=True, null=True) # единицы измерения
quantity = models.CharField(_(u'unit count'), max_length=15, blank=True, null=True) # шт/уп
price = models.FloatField(_(u'price'), blank=True, null=True) # цена
price_discount = models.FloatField(_(u'price discount'), blank=True, null=True) # цена со скидкой
description = models.CharField(_(u'description'), max_length=300, blank=True, null=True)
article = models.TextField(_(u'article'), max_length=5000, blank=True, null=True)
  1. image = models.ImageField(upload_to="uploads/images/", blank=True, null=True)


class Meta:
verbose_name = _(u'Product')
verbose_name_plural = _(u'Products')
__unicode__=lambda self:self.product_name


Нужно чтобы на страничке была формочка, которая умеет фильтровать содержимое. К примеру по цене.
Решение
  • Сначала делаем форму
forms.py
from django import forms
class FilterForm(forms.Form):
lo_price = forms.IntegerField(required=False)
hi_price = forms.IntegerField(required=False)
  • Добавляем отображение формы в шаблон
    <form action="{{ request.get_full_path }}" method="post">
    {{ form.as_p }}
    <input type="submit" value="Submit" />
    </form>
    Переменная {{ request.get_full_path }} говорит говорит текущий урл странички, на которой находимся (django-cms).
  • Теперь обработку этой формы добавляем во вьюху
if context['request'].POST: # If the form has been submitted...
form = FilterForm(context['request'].POST) # A form bound to the POST data


if form.is_valid(): # All validation rules pass
myquery = Q()
if form.cleaned_data['lo_price']:
myquery = Q(price__gt = form.cleaned_data['lo_price'])
if form.cleaned_data['hi_price']:
myquery &= Q(price__lt = form.cleaned_data['hi_price'])
products = Product.objects.filter(
Q(product_type=product_type),
Q(place=place),myquery)






context['products'] = products
context['form'] = form
return context
else:
form = FilterForm() # An unbound form
Тут происходит следующее, если нам запостили данные, то мы производим проверку на валидность данных. Фишка myquery = Q(), это чудесная вещь, создание пустого Q-объекта.
Далее, если нам заданы максимальная и минимальная цена, то мы их добавляем в наш Q-объект.
if context['request'].POST это мы проверяем, что нам пришёл запрос post, такая странная форма записи, потому что наш request засунут в контекст django-cms, т. к. это кусок кода взят из django-cms плагина.
В общем, будет время напишу по-аккуратнее, но суть изложил


Основное
В django можно создавать пустые Q() объекты, где-то час искал


Комментариев нет:

Отправить комментарий