как работает django get_next_by_FOO () запрос? - PullRequest
0 голосов
/ 13 апреля 2020

Я хочу знать, как get_next_by_FOO () / get_previous_by_FOO () извлекает данные из базы данных. кто-нибудь знает код SQL для этого? Может кто-нибудь сказать мне, как это работает за сценой?

1 Ответ

0 голосов
/ 13 апреля 2020

Метод реализован в файле django/db/models/base.py [GitHub] :

    def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
        if not self.pk:
            raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
        op = 'gt' if is_next else 'lt'
        order = '' if is_next else '-'
        param = getattr(self, field.attname)
        q = Q(**{'%s__%s' % (field.name, op): param})
        q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk})
        qs = self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by(
            '%s%s' % (order, field.name), '%spk' % order
        )
        try:
            return qs[0]
        except IndexError:
            raise self.DoesNotExist("%s matching query does not exist." % self.__class__._meta.object_name)

is_next будет True, если вы запрашиваете get_next_by_FOO, и False, если вы запрашиваете get_previous_by_FOO.

Для get_next_by_FOO, таким образом, создается запрос, который выглядит следующим образом:

Model.objects.filter(
    Q(FOO__gt=<i>current_foo</i>)
    Q(FOO=<i>current_foo</i>, pk__gt=<i>current_pk</i>)
).order_by('FOO', 'pk')[0]

Таким образом, он будет искать первые Model объекты, у которых поле FOO такое же, но первичный ключ больше или где поле FOO (строго) больше.

Таким образом, это приведет к тому, что запрос будет выглядеть так:

SELECT *
FROM model
WHERE FOO > <i>current_FOO</i>
   OR (FOO = <i>current_FOO</i> AND id > <i>current_pk</i>)
ORDER BY FOO ASC, id ASC
LIMIT 1

Таким образом, он будет стремиться найти этот элемент, упорядочив записи и выбрав первый.

Для get_previous_by_FOO, запрос аналогичен, за исключением того, что > заменен на <, и мы заказываем в обратном порядке:

SELECT *
FROM model
WHERE FOO < <i>current_FOO</i>
   OR (FOO = <i>current_FOO</i> AND id < <i>current_pk</i>)
ORDER BY FOO DESC, id DESC
LIMIT 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...