Хороша ліба
django-tagging, яка дозволяє тегувати все що завгодно. Вибірку по тегах можна зробити методом get_by_model.
TaggedItem.objects.get_by_model(Post, [u'духовність',u'культура',u'мистецтво'])
і ми отримаємо об'єкти з наступними тегами але з логікою "і". Але мені потрібно такий самий метод, але з логікою "або", тобто вибрати об'єкти де зустрічається хоча би один з перелічених тегів.
Мій варіант методу. Трошки говнокод, але працює. Колись може дойдуть руки навести есетичний марафєт.
def get_by_model_or(self, queryset_or_model, tags):
tags = get_tag_list(tags)
tag_count = len(tags)
if tag_count == 0:
queryset, model = get_queryset_and_model(queryset_or_model)
return model._default_manager.none()
queryset, model = get_queryset_and_model(queryset_or_model)
content_type = ContentType.objects.get_for_model(model)
opts = self.model._meta # return tagging.taggeditem
tagged_item_table = qn(opts.db_table) # `tagging_taggeditem`
where = []
where.append('%s.content_type_id = %%s' % tagged_item_table,)
or_string = "("
or_tuple = ()
params = [content_type.pk]
for i in range(len(tags)):
if i == 0:
or_string += "%s.tag_id = %%s "
else:
or_string += "OR %s.tag_id = %%s "
or_tuple += (tagged_item_table,)
params.append(tags[i].pk)
or_string += ")"
where.append(or_string % or_tuple)
where.append('%s.%s = %s.object_id' % (qn(model._meta.db_table),
qn(model._meta.pk.column),
tagged_item_table))
return queryset.extra(
tables=[opts.db_table],
where=where,
params = params
)