diff --git a/OneCprogsite/settings.py b/OneCprogsite/settings.py index 69e7a70..052e0c7 100644 --- a/OneCprogsite/settings.py +++ b/OneCprogsite/settings.py @@ -70,6 +70,13 @@ if not DEBUG: LANGUAGE_COOKIE_HTTPONLY = True LANGUAGE_COOKIE_SAMESITE = 'Lax' + # Redis + CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0') + CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0') + +if DEBUG: + A = True + CSRF_TRUSTED_ORIGINS = [ 'https://nikdizell.ru', 'https://www.nikdizell.ru', @@ -95,6 +102,7 @@ INSTALLED_APPS = [ 'captcha', 'turnstile', 'products', + 'background_task', ] MIDDLEWARE = [ @@ -288,5 +296,5 @@ CAPTCHA_LENGTH = 6 CAPTCHA_FONT_SIZE = 30 CAPTCHA_IMAGE_SIZE = (150, 50) -TURNSTILE_SITEKEY = '0x4AAAAAAC12NGPpc4TutFWA' -TURNSTILE_SECRET = '0x4AAAAAAC12NCpzKHKE09JaXRDv0smrSAU' +TURNSTILE_SITEKEY = os.getenv('TURNSTILE_SITEKEY') +TURNSTILE_SECRET = os.getenv('TURNSTILE_SECRET') diff --git a/products/views.py b/products/views.py index c62590c..1778c85 100644 --- a/products/views.py +++ b/products/views.py @@ -7,7 +7,7 @@ from programmer.forms import CallbackForm from .forms import OrderForm from django.contrib import messages from django.shortcuts import redirect -from programmer.utils.email_notifications import send_order_notification +from programmer.utils.email_notifications import send_order_notification, send_order_notification_async class ProductListView(MenuContextMixin, BreadcrumbMixin, ListView): @@ -155,10 +155,11 @@ def order_create(request, slug): order.save() # Сохраняем выбранную конфигурацию (уже сохранена в форме) - success = send_order_notification(order) - if success: - order.notification_sent = True - order.save(update_fields=['notification_sent']) + # success = send_order_notification(order) + # if success: + # order.notification_sent = True + # order.save(update_fields=['notification_sent']) + send_order_notification_async(order) messages.success(request, '✅ Ваш заказ принят! Мы свяжемся с вами в ближайшее время.') return redirect('products:product_detail', slug=slug) diff --git a/programmer/utils/email_notifications.py b/programmer/utils/email_notifications.py index 566300d..06eca41 100644 --- a/programmer/utils/email_notifications.py +++ b/programmer/utils/email_notifications.py @@ -252,4 +252,43 @@ def send_test_order_email(): return True except Exception as e: logger.error(f"Test order email failed: {e}") - return False \ No newline at end of file + return False + + +# Асинхронная отправка + +def send_order_notification_async(order): + """Выбирает способ отправки в зависимости от DEBUG.""" + if settings.DEBUG: + # Используем background-tasks + from .tasks import send_order_notification_background + send_order_notification_background(order.id) + return True # задача поставлена в очередь + else: + # Используем Celery + try: + from .tasks import send_order_notification_celery + send_order_notification_celery.delay(order.id) + return True + except (ImportError, AttributeError): + # fallback на синхронную отправку + from .email_notifications import send_order_notification + return send_order_notification(order) + + +def send_multiple_order_notifications_async(orders): + if settings.DEBUG: + from .tasks import send_multiple_order_notifications_background + order_ids = list(orders.values_list('id', flat=True)) + send_multiple_order_notifications_background(order_ids) + return len(order_ids) + else: + try: + from .tasks import send_multiple_order_notifications_celery + order_ids = list(orders.values_list('id', flat=True)) + send_multiple_order_notifications_celery.delay(order_ids) + return len(order_ids) + except (ImportError, AttributeError): + from .email_notifications import send_multiple_order_notifications + return send_multiple_order_notifications(orders) + diff --git a/programmer/utils/tasks.py b/programmer/utils/tasks.py new file mode 100644 index 0000000..f172cac --- /dev/null +++ b/programmer/utils/tasks.py @@ -0,0 +1,56 @@ +from background_task import background +from django.conf import settings +import logging + +logger = logging.getLogger(__name__) + +@background(schedule=0) +def send_order_notification_background(order_id): + """Асинхронная отправка уведомлений о заказе через background-tasks.""" + from .email_notifications import send_order_notification + from products.models import Order + try: + order = Order.objects.select_related('product', 'configuration').get(id=order_id) + success = send_order_notification(order) + if success: + order.notification_sent = True + order.save(update_fields=['notification_sent']) + return success + except Order.DoesNotExist: + logger.error(f"Order #{order_id} not found") + return False + +@background(schedule=0) +def send_multiple_order_notifications_background(order_ids): + """Отправка уведомлений для нескольких заказов.""" + from .email_notifications import send_multiple_order_notifications + from products.models import Order + orders = Order.objects.filter(id__in=order_ids) + return send_multiple_order_notifications(orders) + +try: + from celery import shared_task +except ImportError: + shared_task = None + +if shared_task is not None: + @shared_task + def send_order_notification_celery(order_id): + from .email_notifications import send_order_notification + from products.models import Order + try: + order = Order.objects.select_related('product', 'configuration').get(id=order_id) + success = send_order_notification(order) + if success: + order.notification_sent = True + order.save(update_fields=['notification_sent']) + return success + except Order.DoesNotExist: + return False + + @shared_task + def send_multiple_order_notifications_celery(order_ids): + from .email_notifications import send_multiple_order_notifications + from products.models import Order + orders = Order.objects.filter(id__in=order_ids) + return send_multiple_order_notifications(orders) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d3b21d3..cf5c4c6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ django-taggit django_ckeditor_5 django-allauth django-simple-captcha -django-turnstile \ No newline at end of file +django-turnstile +celery \ No newline at end of file