Files
2026-etpgrf-site/etpgrf_site/typograph/views.py
2026-01-21 01:22:59 +03:00

177 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.db.models import F, Sum
from django.utils import timezone
from django.views.decorators.http import require_POST
from etpgrf.typograph import Typographer
from etpgrf.layout import LayoutProcessor
from etpgrf.hyphenation import Hyphenator
from .models import DailyStat
def index(request):
# Увеличиваем счетчик просмотров главной
try:
today = timezone.now().date()
stat, created = DailyStat.objects.get_or_create(date=today)
DailyStat.objects.filter(pk=stat.pk).update(index_views=F('index_views') + 1)
except Exception as e:
print(f"Stat error: {e}")
return render(request, template_name='typograph/index.html')
def get_stats_summary(request):
"""Возвращает сводную статистику."""
# Убираем try...except для отладки
stats = DailyStat.objects.aggregate(
views=Sum('index_views'),
processed=Sum('process_requests'),
copied=Sum('copy_count'),
chars_in=Sum('chars_in'),
chars_out=Sum('chars_out'),
chars_copied=Sum('chars_copied')
)
# print("Aggregated stats:", stats) # DEBUG
# Функция для форматирования чисел с сокращениями (M, k)
def format_large_number(num):
if num > 1_000_000:
return f"{num / 1_000_000:.3f}M".replace(".", ",")
elif num > 1_000:
return f"{num / 1_000:.2f}k".replace(".", ",")
return str(num)
context = {
'views': f"{(stats['views'] or 0):,}".replace(",", " "),
'processed': f"{(stats['processed'] or 0):,}".replace(",", " "),
'copied': f"{(stats['copied'] or 0):,}".replace(",", " "),
'chars_in': format_large_number(stats['chars_in'] or 0),
'chars_out': format_large_number(stats['chars_out'] or 0),
'chars_copied': format_large_number(stats['chars_copied'] or 0),
}
return render(request, 'typograph/stats_summary.html', context)
@require_POST
def track_copy(request):
"""Увеличивает счетчик копирований и количество скопированных символов."""
try:
char_count = int(request.POST.get('char_count', 0))
today = timezone.now().date()
stat, created = DailyStat.objects.get_or_create(date=today)
DailyStat.objects.filter(pk=stat.pk).update(
copy_count=F('copy_count') + 1,
chars_copied=F('chars_copied') + char_count
)
return HttpResponse("OK")
except (ValueError, TypeError):
return HttpResponse("Invalid char_count", status=400)
except Exception as e:
print(f"Stat error: {e}")
return HttpResponse("Error", status=500)
def process_text(request):
if request.method == 'POST':
text = request.POST.get(key='text', default='')
# 1. Читаем базовые настройки
langs = request.POST.get(key='langs', default='ru')
# 2. Собираем LayoutProcessor
layout_enabled = request.POST.get(key='layout') == 'on'
layout_option = False
if layout_enabled:
process_units = request.POST.get(key='layout_units') == 'on'
if process_units:
custom_units = request.POST.get(key='layout_units_custom', default='').strip()
if custom_units:
process_units = custom_units.split()
layout_option = LayoutProcessor(
langs=langs,
process_initials_and_acronyms=request.POST.get(key='layout_initials') == 'on',
process_units=process_units
)
# 3. Собираем Hyphenator
hyphenation_enabled = request.POST.get(key='hyphenation') == 'on'
hyphenation_option = False
if hyphenation_enabled:
max_len = request.POST.get(key='hyphenation_len', default='12')
try:
max_len = int(max_len)
except (ValueError, TypeError):
max_len = 12
hyphenation_option = Hyphenator(
langs=langs,
max_unhyphenated_len=max_len
)
# 4. Читаем Sanitizer
sanitizer_enabled = request.POST.get(key='sanitizer_enabled') == 'on'
sanitizer_option = None
if sanitizer_enabled:
sanitizer_option = request.POST.get(key='sanitizer', default='etp')
# 5. Читаем Hanging Punctuation
hanging_enabled = request.POST.get(key='hanging_enabled') == 'on'
hanging_option = None
if hanging_enabled:
hanging_option = request.POST.get(key='hanging_punctuation', default='both')
# 6. Собираем общие опции
options = {
'langs': langs,
'process_html': True,
'quotes': request.POST.get('quotes') == 'on',
'layout': layout_option,
'unbreakables': request.POST.get(key='unbreakables') == 'on',
'hyphenation': hyphenation_option,
'symbols': request.POST.get(key='symbols') == 'on',
'hanging_punctuation': hanging_option,
'mode': request.POST.get(key='mode', default='mixed'),
'sanitizer': sanitizer_option,
}
# --- ДИАГНОСТИКА ---
# print("Typographer options:", options)
# -------------------
# Создаем экземпляр типографа
typo = Typographer(**options)
# Обрабатываем текст
processed = typo.process(text)
# --- СБОР СТАТИСТИКИ ---
try:
today = timezone.now().date()
stat, created = DailyStat.objects.get_or_create(date=today)
# Обновляем атомарные поля
DailyStat.objects.filter(pk=stat.pk).update(
process_requests=F('process_requests') + 1,
chars_in=F('chars_in') + len(text),
chars_out=F('chars_out') + len(processed),
# total_processing_time_ms мы пока не считаем, чтобы не усложнять
)
# JSON с настройками пока не пишем, чтобы не усложнять (как договаривались)
except Exception as e:
print(f"Stat error: {e}")
# -----------------------
return render(
request,
template_name='typograph/result_fragment.html',
context={'processed_text': processed}
)
return HttpResponse(status=405)