mod: порядок отдачи следующей случайной цитаты чтоб не возникало петель
This commit is contained in:
@@ -65,6 +65,13 @@ class CommonContextMixin:
|
|||||||
# --- 1. ЛОГИКА ИСТОРИИ СЕССИИ (Предотвращение петель) ---
|
# --- 1. ЛОГИКА ИСТОРИИ СЕССИИ (Предотвращение петель) ---
|
||||||
seen_ids = request.session.get('seen_ids', [])
|
seen_ids = request.session.get('seen_ids', [])
|
||||||
|
|
||||||
|
# Если мы переключили контекст (например, выбрали другой тег), имеет смысл сбросить историю?
|
||||||
|
# Или можно оставить, так как уникальность ID глобальна.
|
||||||
|
# Проблема: если seen_ids забит цитатами, а мы выбрали тег, где всего 2 цитаты,
|
||||||
|
# и они обе случайно оказались в seen_ids (потому что мы их видели раньше без тега),
|
||||||
|
# то exclude исключит всё.
|
||||||
|
|
||||||
|
# Решение: принудительно добавить текущую цитату, если её нет
|
||||||
if dq.id not in seen_ids:
|
if dq.id not in seen_ids:
|
||||||
seen_ids.append(dq.id)
|
seen_ids.append(dq.id)
|
||||||
if len(seen_ids) > 100:
|
if len(seen_ids) > 100:
|
||||||
@@ -100,12 +107,39 @@ class CommonContextMixin:
|
|||||||
dq.save(update_fields=['iViewCounter'])
|
dq.save(update_fields=['iViewCounter'])
|
||||||
|
|
||||||
# --- 6. ВЫБОР СЛЕДУЮЩЕЙ ЦИТАТЫ ---
|
# --- 6. ВЫБОР СЛЕДУЮЩЕЙ ЦИТАТЫ ---
|
||||||
|
# Сначала пробуем найти следующую цитату, которую мы еще не видели
|
||||||
dq_next = queryset.exclude(id__in=seen_ids).order_by('?').first()
|
dq_next = queryset.exclude(id__in=seen_ids).order_by('?').first()
|
||||||
|
|
||||||
|
# Если таких нет (мы посмотрели все цитаты в этом контексте/теге)
|
||||||
if dq_next is None:
|
if dq_next is None:
|
||||||
request.session['seen_ids'] = []
|
# СБРОС ИСТОРИИ!
|
||||||
|
# Мы посмотрели всё, что было по этому фильтру. Начинаем круг заново.
|
||||||
|
# Но удалять ВСЮ историю сессии опасно (вдруг мы вернемся в общий список).
|
||||||
|
# Лучше локально для выбора следующей цитаты игнорировать историю,
|
||||||
|
# но возможно стоит очистить сессию, чтобы цикл начался чисто.
|
||||||
|
|
||||||
|
# Вариант: Очистить seen_ids, чтобы в следующий раз (на некст странице) список был пуст?
|
||||||
|
# Или просто выбрать любую КРОМЕ текущей?
|
||||||
|
|
||||||
dq_next = queryset.exclude(id=dq.id).order_by('?').first()
|
dq_next = queryset.exclude(id=dq.id).order_by('?').first()
|
||||||
|
|
||||||
|
# Если мы действительно прошли весь цикл по тегу, логично сбросить seen_ids,
|
||||||
|
# чтобы пользователь мог заново проходить этот список случайно, а не "застревать" на последних.
|
||||||
|
# Однако, очистка seen_ids здесь повлияет на глобальную сессию.
|
||||||
|
# Если тег "red" (2 цитаты), мы их посмотрели. seen_ids=[1,2].
|
||||||
|
# queryset=[1,2]. exclude -> []. dq_next=None.
|
||||||
|
# Fallback: exclude(current) -> [1] (если cur=2). dq_next=1.
|
||||||
|
# User goes to 1. seen_ids=[1,2] (set logic handles dupes/order? No, list appends).
|
||||||
|
# seen_ids=[1,2,1].
|
||||||
|
# Next request (dq=1). queryset=[1,2]. exclude([1,2,1]) -> []. dq_next=2.
|
||||||
|
# It loops 1-2-1-2.
|
||||||
|
|
||||||
|
# Чтобы разорвать этот малый круг и сделать его снова "случайным" (если там >2 элементов, но меньше 100),
|
||||||
|
# нужно очистить seen_ids, если мы уткнулись в конец списка.
|
||||||
|
# Но удалять нужно только те ID, которые принадлежат этому queryset? Сложно.
|
||||||
|
# Проще очистить всё, так как пользователь явно "наелся" текущим контекстом и пошел по второму кругу.
|
||||||
|
request.session['seen_ids'] = []
|
||||||
|
|
||||||
if dq_next:
|
if dq_next:
|
||||||
context.update({"NEXT": dq_next.id})
|
context.update({"NEXT": dq_next.id})
|
||||||
context.update({"NEXT_TXT": pytils.translit.slugify(dq_next.szContent.lower()[:120])})
|
context.update({"NEXT_TXT": pytils.translit.slugify(dq_next.szContent.lower()[:120])})
|
||||||
@@ -160,7 +194,16 @@ class IndexView(CommonContextMixin, TemplateView):
|
|||||||
active_qs, _ = self.get_filtered_queryset()
|
active_qs, _ = self.get_filtered_queryset()
|
||||||
|
|
||||||
dq = None
|
dq = None
|
||||||
|
seen_ids = self.request.session.get('seen_ids', [])
|
||||||
|
|
||||||
if active_qs is not None:
|
if active_qs is not None:
|
||||||
|
# Если мы в режиме фильтрации, тоже стараемся не показывать то, что уже видели
|
||||||
|
dq = active_qs.exclude(id__in=seen_ids).order_by('?').first()
|
||||||
|
|
||||||
|
# Если после фильтрации ничего не осталось (мы просмотрели все цитаты тега)
|
||||||
|
if dq is None:
|
||||||
|
# Сбрасываем историю и берем любую
|
||||||
|
self.request.session['seen_ids'] = []
|
||||||
dq = active_qs.order_by('?').first()
|
dq = active_qs.order_by('?').first()
|
||||||
|
|
||||||
if dq is None:
|
if dq is None:
|
||||||
@@ -169,7 +212,6 @@ class IndexView(CommonContextMixin, TemplateView):
|
|||||||
active_qs = TbDictumAndQuotes.objects.all()
|
active_qs = TbDictumAndQuotes.objects.all()
|
||||||
|
|
||||||
# Случайная цитата (с учетом истории, чтобы главная страница тоже не зацикливалась)
|
# Случайная цитата (с учетом истории, чтобы главная страница тоже не зацикливалась)
|
||||||
seen_ids = self.request.session.get('seen_ids', [])
|
|
||||||
dq = active_qs.exclude(id__in=seen_ids).order_by('?').first()
|
dq = active_qs.exclude(id__in=seen_ids).order_by('?').first()
|
||||||
|
|
||||||
if dq is None:
|
if dq is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user