LINUX.ORG.RU
ФорумTalks

Пагинация - правильно ли я делаю?

 , , ,


0

1

Очень тупой и очень нубский вопрос.

Никогда не делал пагинацию, т.к. не понимал, как она работает. Не знал, что делать, если количество записей не делится без остатка. На днях получилось вот что (да, код на питоне, но вообще в будущем буду использовать и в PHP, и да, есть плагин для фласка, но я хочу понять, как это работает):

total_count = 115
count_per_page = 50
page_count = None

if total_count % count_per_page != 0:
   page_count = (total_count - (total_count % count_per_page)) / count_per_page
else:
   page_count = total_count / count_per_page


Да, тут только код на проверку, и еще надо много писать, но по сути это пример. Тут на самом деле добавляется еще одна страница с оставшимися записями. А начало лимита вывода записей из БД планируется делать так: номер страницы умножать на количество записей на странице.

И скорее всего способ ОЧЕНЬ кривой, но это первое, что пришло в голову.

Как делать пагинацию правильно? Гугл выдает всякие jQuery и т.п., а надо именно с нуля. Просто хочу наконец разобраться.

На всякий случай размещаю тему в толксах.



Последнее исправление: ozz_is_here (всего исправлений: 1)

Так а в чём проблема, просто на последней странице показываешь остатки.

А вообще я бы предпочел чтобы на последней странице всегда было число постов, равное count_per_page. Благодаря этому часть постов попадёт с предпоследней страницы на последнюю, пока она не заполнится. А то бесит когда оставляешь пост, который оказывается заканчивает текущую страницу, а ледующий пост создаёт новую и твой пост уже мало кто увидит.

По-моему пагинацию так ещё никто не делал, а зря.

Deleted
()
Ответ на: комментарий от Deleted

Так а в чём проблема, просто на последней странице показываешь остатки.

Ну так я и написал, что добавляется еще одна страница с остатками.

Я вообще про сам способ. Так ли вообще делается, или делает ли кто-нибудь так вообще.

ozz_is_here
() автор топика
PER_PAGE = 10
ITEMS = []

if len(ITEMS) % PER_PAGE == 0:
    TOTAL_PAGES = len(ITEMS) // PER_PAGE  
else:
    TOTAL_PAGES = len(ITEMS) // PER_PAGE  + 1

show_items = ITEMS[(ACTIVE_PAGE - 1) * PER_PAGE: ACTIVE_PAGE * PER_PAGE]
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 3)
Ответ на: комментарий от vvn_black

А, точно, спасибо большое. Забыл про его существование.

ozz_is_here
() автор топика
Последнее исправление: ozz_is_here (всего исправлений: 1)

Ты лучше с пагинацией в процессорах разберись. Тут у нас очередные Спектры.

pacify ★★★★★
()

divmod() — это даже не стандартная библиотека, это builtin.

aidaho ★★★★★
()

номер страницы умножать на количество записей на странице.

И что это даст фактически? Представь что ты выводишь на странице по две записи, у тебя в базе лежат записи с id 1, 2, 4, 8, 16, 32. Как ты будешь разбивать это на страницы имея только номер страницы и количество записей? Тебе нужно хранить последний айдишник на странице, и уже от него считать лимит этот, при этом не по айдишникам, а по количеству записей. Твой номер страницы это лишь метка о том, «сколько лимитов» надо пропустить прежде чем показывать очередную пачку записей.

micronekodesu ★★★
()

Учти, что limit/offset-пагинация отсасывает на большом количестве записей. Ну и страдает неправильной выдачей при вставке/удалении записей между запросами.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Да, именно такое планировалось, но раз уж

limit/offset-пагинация отсасывает на большом количестве записей. Ну и страдает неправильной выдачей при вставке/удалении записей между запросами

То это так себе вариант.

ozz_is_here
() автор топика
Ответ на: комментарий от ozz_is_here

То это так себе вариант.

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

Но если у тебя поле (или комбинация полей), по которому производится сортировка, содержит уникальные значения, то можно воспользоваться т.н. «keyset pagination» (или «cursor-based pagination», или «seek pagination»). Допустим, у тебя есть поле id, которое содержит уникальные идентификаторы записей, причем более поздней записи соответствует бОльший идентификатор (другой возможных кандидат — совокупность полей (created_at, id)).

Рассмотрим такую выдачу:

  • id=42
  • id=43
  • ...
  • id=51

Ссылка на предыдущую страницу будет иметь вид /my_table/list?before=42, а на следующую — /my_table/list?after=42 (название переменных запроса подберёшь себе по вкусу).

Запрос на получение записей для предыдущей страницы (тебе ещё нужно будет «развернуть» результат в БД либо в приложении):

  select *
    from my_table
order by id desc
   where id < 42
   limit PER_PAGE;

Получение записей для следующей страницы (для этого запроса «разворачивать» результат не надо):

  select *
    from my_table
order by id asc
   where id > 51
   limit PER_PAGE;

Естественно, нужен будет индекс по полю или комбинации полей, учавствующих в сортировке и выборке через where.

Недостаток этого метода — ты можешь переходить только на следующую/предыдущую страницу, но не на произвольную страницу (страницу с номером N).

theNamelessOne ★★★★★
()
page_count = (total_count + count_per_page - 1) / count_per_page
baka-kun ★★★★★
()
Ответ на: комментарий от theNamelessOne

Это годится для бесконечной прокрутки, а там где записи укладываются по порядку и не поднимаются все же от offset не убежать.
Я еще люблю подобный метод в комбинации с апи курсорами(не путать с курсорами БД), где API отдает некий не долгоживущий идентификатор в качестве курсора.
Есть такой вариант запрашивать id всех записей и потом как отдельными чанками их загружать. Это довольно-таки быстро выходит, но опять же не везде применимо.

ritsufag ★★★★★
()
Ответ на: комментарий от theNamelessOne

Например как здесь, внутри темы. Посты идут один за другим и не поднимаются/опускаются.
В то же время в трекере темы наоборот часто меняют позицию(грубо говоря бампаются).

ritsufag ★★★★★
()
Ответ на: комментарий от ritsufag

Не вижу, что мешает использовать keyset-пагинацию в обоих случаях (положим, что нам не нужна операция «переход на произвольную страницу»).

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

Если не нужна то да, но еще могут быть проблемы с тем чтобы обратится к элементу напрямую по ссылке.
Можно обойти эти проблемы запрашивая все идентификаторы постов в треде, таким образом мы сможем свободно переходить к посту/отрезку в дискуссии. Конечно этот вариант без жс не реализовать, но в целом он иметь право на жизнь.
Так например поступает discourse и его клоны.

ritsufag ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.