Перехват NotImplementedError, не выполняющий код, кроме блока

#django #django-orm

#django #django-orm

Вопрос:

PostgreSQL может иметь .distint('field name') запросы к базе данных, однако Sqlite — нет, поэтому я создал блок try / except, который должен запускать более простой запрос, если пользователь использует sqlite3.

 try:
    qs = qs.filter(tag__istartswith=self.q).order_by('tag').distinct('tag')
except NotImplementedError:
    qs = qs.filter(tag__istartswith=self.q)
  

Поэтому, если пользователь использует Sqlite, я бы ожидал, что простой запрос в блоке except будет выполнен, однако возникает исключение, и простой запрос никогда не выполняется:

 raise NotImplementedError('DISTINCT ON fields is not supported by this database backend')
NotImplementedError: DISTINCT ON fields is not supported by this database backend
  

У вас есть какие-либо идеи, почему это работает не так, как ожидалось?

Спасибо

Ответ №1:

Потому что наборы запросов являются ленивыми, и ошибка возникает не при построении запроса, а при его фактической оценке.

Вы можете попробовать принудительно вычислить свой запрос, чтобы перехватить исключение:

 try:
    qs = qs.filter(tag__istartswith=self.q).order_by('tag').distinct('tag')
    dummy_boolean_var = qs.exists()
except NotImplementedError:
    qs = qs.filter(tag__istartswith=self.q)
  

РЕДАКТИРОВАТЬ: По-видимому, моя непроверенная версия не сработала, поскольку назначение в except предложении пытается изменить исходный запрос. Это рабочая версия, протестированная OP:

 try:
    qa = qs
    qs = qs.filter(tag__istartswith=self.q).order_by('tag').distinct(‌​'tag')
    dummy_boolean_var = qs.exists()
except NotImplementedError:
    qs = qa
    qs = qs.filter(tag__istartswith=self.q)
  

Комментарии:

1. Спасибо за ваш ответ. Это работает, хотя мне пришлось внести небольшое изменение. Когда первый запрос qs (try) завершается с ошибкой, это приводит к сбою второго (except) qs, поскольку кажется, что первая попытка qs изменила qs. Поэтому мне нужно сделать что-то вроде этого: try:n qa = qsn qs = qs.filter(tag__istartswith=self.q).order_by('tag').distinct('tag')n dummy_boolean_var = qs.exists()n except NotImplementedError:n qs = qan qs = qs.filter(tag__istartswith=self.q) . Извините за плохое форматирование, не уверен, как его улучшить.

2. @TomBrock Спасибо за обновление, я отредактировал свой ответ и включил вашу рабочую версию, чтобы помочь будущим посетителям.