Преобразовать логическое выражение в набор запросов django - PullRequest
1 голос
/ 08 июня 2011

На моем сайте django есть метки, и я хотел бы разрешить URL-адреса вида:

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

Что на английском языке будет означать:

Найтипредметы, помеченные (foo AND собака) ИЛИ (коза и кошка).

По сути, мне нужен способ свести это к запросам с использованием API Django.В настоящее время я просто хочу поддерживать AND, OR и круглые скобки.

Я предполагаю, что есть библиотеки для интерпретации логических выражений такого рода, но я не смог найти ничего вне полноценной поисковой системы.,Есть ли какие-то хитрости для этого или хорошие начальные точки с использованием API Django?

В данный момент мой код довольно прост, но он поддерживает или ИЛИ запросы или И запросы, но не их объединенные (таким образом, также нет скобок).

РЕДАКТИРОВАТЬ : Я вполне уверен, что если бы я мог разбить это на ряд запросов И и ИЛИ, ябыло бы все готово ... но я не могу обдумать, как перейти от произвольно заданного в скобках логического запроса к логически полезному пониманию запроса.

Вот код, который у меня есть до сих пор, на случай, если онполезно.Я не использую модуль тегов (хотя, может быть, мне следует), и код все еще черновой, но ...

@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 голосов
/ 08 июня 2011

Использование Q объектов .

Для анализа просто установите регулярное выражение в вашем 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 и отличается, если вы используете свою собственную реализацию.

...