Получить позицию совпадений регулярных выражений в объектах базы данных, используя Django - PullRequest
0 голосов
/ 09 мая 2020

У меня есть приложение Django с базой данных Postgres, которое принимает пользовательский ввод, создает регулярное выражение на основе этого ввода и возвращает записи базы данных, которые соответствуют этому регулярному выражению, а также начальной и конечной позициям этого совпадения. Текущая реализация выглядит примерно так:

models.py:

class SampleInputModel(models.Model):
    target_field = models.CharField()

class SampleInputModelForm(ModelForm):
    class Meta:
        model = SampleInputModel
        fields = '__all__'

class RecordObject(models.Model):
    record_name = models.TextField()
    record_string = models.TextField()

views.py:

find_regex_match(form_dict, one_record, terminating_word='keyword'):
    import re
    search_pattern = f'({form_dict['target_field']}).*(terminating_word)'
    for match in re.finditer(search_pattern, one_record.record_string):
        return '{}\t{}\t{}\t{}\n'.format(
            one_record.record_name, match.start(), match.end(), 
            one_record.record_string[match.start():match.end()]
        )

def home(request):
    if request.method == 'POST':
        form = SampleInputModelForm(request.POST)
        if form.is_valid():
            form = form.save(commit=False)
            form = model_to_dict(form)
            results = ''
            for one_record in RecordObject.objects.all():
                results += find_regex_match(form_dict, one_record)
            return render(request, 'results.html', {'results': results})
    else:
        form = SampleInputModelForm()

    return render(request, 'home.html', {'form': form})

Это работает и занимает ~ 1,2 секунды на средний к завершению. Однако я чувствую, что есть лучший способ обработать результаты, чем просто передавать огромную необработанную строку в шаблон для рендеринга. Я хотел переключиться на использование некоторых API Django для фильтрации базы данных, чтобы можно было передавать наборы запросов в шаблоны. Новая версия кода выглядит так:

def home(request):
    if request.method == 'POST':
        form = SampleInputModelForm(request.POST)
        if form.is_valid():
            form = form.save(commit=False)
            form = model_to_dict(form)

            search_pattern = f'({form_dict['target_field']}).*(terminating_word)'
            results = RecordObject.objects.filter(record_string__iregex=search_pattern)

            return render(request, 'results.html', {'results': results})
    ...

Этот запрос завершается очень быстро (<0,005 секунды) и кажется более Django -y (и я думаю, что смогу отформатировать вещи намного проще использовать объект QuerySet вместо необработанной строки в результатах. html), но я не знаю, как извлечь нужную мне информацию из результатов. Я попробовал, объединив два подхода: </p>

def home(request):
    if request.method == 'POST':
        form = SampleInputModelForm(request.POST)
        if form.is_valid():
            form = form.save(commit=False)
            form = model_to_dict(form)

            search_pattern = f'({form_dict['target_field']}).*(terminating_word)'
            results = ''
            for record_match in RecordObject.objects.filter(record_string__iregex=search_pattern):
                results += find_regex_match(form_dict, record_match)

            return render(request, 'results.html', {'results': results})
    ...

Но это медленнее, чем два других подхода, в среднем около 3 секунд на выполнение. Это имеет смысл, поскольку я выполняю поиск по регулярному выражению (в основном) дважды. Есть ли лучший способ получить необходимую мне информацию после фильтрации базы данных с помощью регулярного выражения, не жертвуя слишком большой скоростью? Также приветствуются любые общие комментарии к коду. Спасибо!

...