1 Commits

Author SHA1 Message Date
erjemin 9cd147b0d7 mod: оптимизированные svg, favicon-ы и другая мелочь.
Build and Push Docker Image / build-and-push (push) Successful in 1m0s
2026-03-22 16:54:36 +03:00
3 changed files with 17 additions and 39 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ upstream dq-django {
# 2. Конфигурируем сервер
server {
server_name dq.cube2.ru; # Основное доменное имя
server_name dq.cube2.ru dq2.cube2.ru; # Основное доменное имя
# Слушаем 80 порт (Certbot потом добавит сюда редирект на 443 и настройки SSL)
listen 80;
+11 -34
View File
@@ -12,7 +12,6 @@ from django.core.exceptions import ObjectDoesNotExist
from django.views.generic import DetailView, TemplateView
import time
import pytils
import random
from web.models import TbDictumAndQuotes, TbImages, TbAuthor
@@ -99,11 +98,9 @@ class CommonContextMixin:
# --- 4. ВЫБОР КАРТИНКИ ---
if dq.kImages_id is None:
if len(tags) != 0:
# Используем Python random вместо order_by('?') для производительности
tagged_images = list(TbImages.objects.filter(tags__name__in=tags).values_list('id', 'imFile'))
if tagged_images:
tagged_image = tagged_images[random.randint(0, len(tagged_images) - 1)]
context.update({'IMAGE': tagged_image[1]})
tagged_image = TbImages.objects.filter(tags__name__in=tags).order_by('?').first()
if tagged_image:
context.update({'IMAGE': tagged_image.imFile})
else:
context.update({'IMAGE': dq.kImages.imFile})
@@ -113,13 +110,7 @@ class CommonContextMixin:
# --- 6. ВЫБОР СЛЕДУЮЩЕЙ ЦИТАТЫ ---
# Сначала пробуем найти следующую цитату, которую мы еще не видели
# Используем Python random вместо order_by('?') для производительности
unseen_ids = queryset.exclude(id__in=seen_ids).values_list('id', flat=True)
if unseen_ids:
dq_next_id = list(unseen_ids)[random.randint(0, len(unseen_ids) - 1)]
dq_next = queryset.filter(id=dq_next_id).first()
else:
dq_next = None
dq_next = queryset.exclude(id__in=seen_ids).order_by('?').first()
# Если таких нет (мы посмотрели все цитаты в этом контексте/теге)
if dq_next is None:
@@ -132,12 +123,7 @@ class CommonContextMixin:
# Вариант: Очистить seen_ids, чтобы в следующий раз (на некст странице) список был пуст?
# Или просто выбрать любую КРОМЕ текущей?
other_ids = list(queryset.exclude(id=dq.id).values_list('id', flat=True))
if other_ids:
dq_next_id = other_ids[random.randint(0, len(other_ids) - 1)]
dq_next = queryset.filter(id=dq_next_id).first()
else:
dq_next = None
dq_next = queryset.exclude(id=dq.id).order_by('?').first()
# Если мы действительно прошли весь цикл по тегу, логично сбросить seen_ids,
# чтобы пользователь мог заново проходить этот список случайно, а не "застревать" на последних.
@@ -214,19 +200,13 @@ class IndexView(CommonContextMixin, TemplateView):
if active_qs is not None:
# Если мы в режиме фильтрации, тоже стараемся не показывать то, что уже видели
unseen_ids = list(active_qs.exclude(id__in=seen_ids).values_list('id', flat=True))
if unseen_ids:
dq = active_qs.filter(id=unseen_ids[random.randint(0, len(unseen_ids) - 1)]).first()
else:
dq = None
dq = active_qs.exclude(id__in=seen_ids).order_by('?').first()
# Если после фильтрации ничего не осталось (мы просмотрели все цитаты тега)
if dq is None:
# Сбрасываем историю и берем любую
self.request.session['seen_ids'] = []
all_ids = list(active_qs.values_list('id', flat=True))
if all_ids:
dq = active_qs.filter(id=all_ids[random.randint(0, len(all_ids) - 1)]).first()
dq = active_qs.order_by('?').first()
if dq is None:
# Если тег не задан, или по тегу ничего не нашлось совсем
@@ -234,14 +214,11 @@ class IndexView(CommonContextMixin, TemplateView):
active_qs = TbDictumAndQuotes.objects.all()
# Случайная цитата (с учетом истории, чтобы главная страница тоже не зацикливалась)
unseen_ids = list(active_qs.exclude(id__in=seen_ids).values_list('id', flat=True))
if unseen_ids:
dq = active_qs.filter(id=unseen_ids[random.randint(0, len(unseen_ids) - 1)]).first()
else:
dq = active_qs.exclude(id__in=seen_ids).order_by('?').first()
if dq is None:
self.request.session['seen_ids'] = []
all_ids = list(active_qs.values_list('id', flat=True))
if all_ids:
dq = active_qs.filter(id=all_ids[random.randint(0, len(all_ids) - 1)]).first()
dq = active_qs.order_by('?').first()
if dq:
# Используем миксин, ОБЯЗАТЕЛЬНО передаем active_qs
+5 -4
View File
@@ -1,3 +1,4 @@
% cat docker-compose.yaml
# ==============================================================================
# Docker Compose для PRODUCTION
# Этот файл запускается на боевом сервере.
@@ -48,7 +49,7 @@ services:
mkdir -p /app/public/media/errors &&
cp /home/app/web/dicquo/templates/static_404.html /app/public/media/errors/404.html &&
cp /home/app/web/dicquo/templates/static_500.html /app/public/media/errors/500.html &&
gunicorn --workers 2 --timeout 15 --bind 0.0.0.0:8000 dicquo.wsgi:application"
gunicorn --workers 3 --bind 0.0.0.0:8000 dicquo.wsgi:application"
# 4. Проброс портов (Внешний Nginx -> localhost:8010)
ports:
@@ -91,9 +92,9 @@ services:
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/').read()"]
interval: 30s # Проверка каждые 30 секунд
timeout: 5s # Таймаут ответа - 5 секунд
start_period: 60s # Даем 60 секунд на стартап (миграции + collectstatic + gunicorn запуск)
retries: 5 # Unhealthy после 5 неудачных попыток
timeout: 3s # Таймаут ответа - 3 секунды
start_period: 10s # Даем 10 секунд на стартап перед первой проверкой
retries: 3 # Unhealthy после 3 неудачных попыток
# 9. Логирование (Ротация)
logging: