# coding=utf-8
"""
"""
from __future__ import absolute_import
import sqlalchemy as sa
from abilian.i18n import _
from abilian.core.models.tag import Tag, entity_tag_tbl
from .extension import ENTITY_DEFAULT_NS_ATTR
from ..search.criterion import BaseCriterion
[docs]class TagCriterion(BaseCriterion):
"""
Filter entities with selected tag(s).
"""
form_default_value = u''
def __init__(self, *args, **kwargs):
if len(args) == 0:
kwargs.setdefault('name', 'tags')
if len(args) < 2:
kwargs.setdefault('label', _(u'Tags'))
super(TagCriterion, self).__init__(*args, **kwargs)
@BaseCriterion.model.setter
def model(self, model):
BaseCriterion.model.fset(self, model)
self.ns = getattr(model, ENTITY_DEFAULT_NS_ATTR)
@property
def valid_tags(self):
join_clause = entity_tag_tbl.join(
self.model,
self.model.id == entity_tag_tbl.c.entity_id,
)
model_tags = sa.sql.select([entity_tag_tbl.c.tag_id], from_obj=join_clause)
return Tag.query.filter(Tag.ns == self.ns,
Tag.id.in_(model_tags))\
.all()
[docs] def get_request_values(self, request):
tag_ids = []
for val in request.values.getlist(self.name):
try:
tag_ids.append(int(val))
except ValueError:
pass
valid_tags = set(self.valid_tags)
tags = []
for tid in tag_ids:
t = Tag.query.get(tid)
if t in valid_tags:
tags.append(t)
return tags
[docs] def filter(self, query, module, request, searched_text, *args, **kwargs):
"""
"""
tags = self.get_request_values(request)
if not tags:
return query
cond = sa.sql.exists(
sa.sql.select([1], entity_tag_tbl.c.entity_id == self.model.id)
)
return query.filter(cond)
@property
def form_filter_type(self):
return "select"
@property
def form_unset_value(self):
return []
@property
def form_filter_args(self):
# expected value: [list of selectable items, is multiple?]
return [
[(unicode(t.id), t.label) for t in self.valid_tags],
True,
]