【问题标题】:Convert Boolean expression to django queryset将布尔表达式转换为 django 查询集
【发布时间】:2011-06-08 06:44:34
【问题描述】:

我在我的 django 网站上设置了标签,我想允许以下形式的 url:

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

在英语中的意思是:

查找标记为 (foo AND dog) OR (goat AND cat) 的项目。

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

我想有一些库可以解释这种布尔值,但我无法在成熟的搜索引擎之外找到任何库。使用 Django API 是否有任何技巧或良好的起点?

目前,我的代码非常基本,但它支持 either 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 查询集并渲染它。也许不是最有效的,但似乎到目前为止有效。

【问题讨论】:

    标签: django tagging boolean-logic


    【解决方案1】:

    使用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 不同,如果您使用自己的实现,则不同。

    【讨论】:

    • 我在上面添加了更多细节。希望足以让它有意义。
    猜你喜欢
    • 2022-01-19
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 2015-04-14
    相关资源
    最近更新 更多