将布尔表达式转换为django queryset

时间:2011-06-08 06:44:34

标签: django tagging boolean-logic

我在django网站上贴了标签,我想允许这种形式的网址:

http://example.com/search/tags/(foo+dog)|(goat+cat)

用英语表示:

  

找到标有(foo和dog)OR(山羊和猫)的物品。

基本上我需要的是一种使用Django API将其削减为查询的方法。目前,我只想支持AND,OR和括号。

我想有一些用于解释此类布尔人的库,但我还没有找到任何一个完整的搜索引擎。使用Django API有没有做这个或好起点的技巧?

目前,我的代码非常基本,但它支持 OR查询 AND查询,但不能将它们合并在一起(因此也没有括号)。

修改: 我相信如果我可以把它排成一系列的AND和OR查询,我就会全部设置......但我无法思考如何从随机括号内的布尔查询转到逻辑上有用的了解查询。

这是我到目前为止的代码,以防它有用。我没有使用标记模块(虽然我应该这样做),代码仍然很多,但是...

@login_required
def view_opinions_by_tag(request, tagValues):
    '''Displays opinions tagged by a user with certain tags.

    Given a set of tags separated by pluses, pipes, and parentheses, unpack
    the set of tags and display the correct opinions. Currently only supports
    pluses (AND filters), and pipes (OR filters).
    '''
    if '|' in tagValues:
        # it's an or query.
        tagList = tagValues.split('|')
        tags = Tag.objects.filter(tag__in = tagList, user = request.user)\
            .values_list('pk', flat=True)
        faves = Favorite.objects.filter(tags__in = list(tags), user = request.user).distinct()

    elif '+' in tagValues:
        # it's an and query - not very efficient.
        tagList = tagValues.split('+')
        tagObject = Tag.objects.get(tag = tagList[0], user = request.user)
        faves = Favorite.objects.filter(tags = tagObject, user = request.user)
        for tag in tagList[1:]:
            tagObject = Tag.objects.filter(tag = tag, user = request.user)
            faves = faves.filter(tags = tagObject, user = request.user).distinct()

    else:
        # it's a single tag
        tag = Tag.objects.get(tag = tagValues, user = request.user)
        faves = Favorite.objects.filter(tags = tag, user = request.user)

从这里开始,我基本上采用了faves查询集,然后渲染它。也许不是最有效的,但到目前为止似乎有效。

1 个答案:

答案 0 :(得分:0)

使用Q objects

对于解析,只需在urls.py中设置一个正则表达式即可获得所需内容:

url(r'^/search/tags/(?p<query>[a-z\-\+\|])$')

在您的观点中:

def your_view(request, query):
    for and_exp in query.split('|'):
        for tag in and_exp.split('+'):
            # do your stuff with q object

编辑

实际上这是一个通用的答案,但我只是意识到你在谈论标签,因此有很多关系。

这在很大程度上取决于实施情况,所以您必须向我们提供更多详细信息。

如果您使用django-tagging,则可以使用Object.tagged.with_all('tag1', 'tag2')

进行多次查询

django-taggit不同,如果您使用自己的实现,则会有所不同。