Site/products/views.py

183 lines
7.6 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.views.generic import ListView, DetailView, DetailView
from programmer.mixins import MenuContextMixin, BreadcrumbMixin
from .models import Product, ProductCategory, Configuration
from django.shortcuts import get_object_or_404
from django.http import Http404
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, send_order_notification_async
from django.utils.decorators import method_decorator
from django.contrib.admin.views.decorators import staff_member_required
class ProductListView(MenuContextMixin, BreadcrumbMixin, ListView):
model = Product
template_name = 'products/product_list.html'
context_object_name = 'products'
paginate_by = 12
def get_breadcrumbs(self):
return [{'title': 'Продукты', 'url_name': None}]
def get_queryset(self):
qs = (
Product.objects
.filter(is_published=True)
.select_related('category')
.prefetch_related('configurations')
)
# Фильтр по категории
category_slug = self.request.GET.get('category')
if category_slug:
self.current_category = get_object_or_404(ProductCategory, slug=category_slug)
qs = qs.filter(category=self.current_category)
else:
self.current_category = None
# Фильтр по конфигурации
config_slug = self.request.GET.get('configuration')
if config_slug:
self.current_configuration = get_object_or_404(Configuration, slug=config_slug)
qs = qs.filter(configurations=self.current_configuration)
else:
self.current_configuration = None
# ordering уже задан в Meta, явный вызов order_by не нужен,
# но оставляем для явности и возможного расширения сортировки
return qs.order_by('-time_create')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = ProductCategory.objects.all()
context['configurations'] = Configuration.objects.all()
context['current_category'] = self.current_category
context['current_configuration'] = self.current_configuration
context['title'] = "Продукты 1С | Модули и расширения | С.Н.А. Технологии"
context['meta_description'] = (
"Готовые модули, расширения и программные продукты для 1С: Предприятие. "
"Фильтрация по конфигурациям и категориям."
)
context['meta_keywords'] = "1С модули, расширения 1С, программы 1С, купить 1С, продукты 1С"
form = CallbackForm()
if self.request.user.is_authenticated:
if 'captcha' in form.fields:
del form.fields['captcha']
context.update({
'form': form,
})
return context
class ProductDetailView(MenuContextMixin, BreadcrumbMixin, DetailView):
model = Product
template_name = 'products/product_detail.html'
context_object_name = 'product'
def get_object(self, queryset=None):
product = super().get_object(queryset=queryset)
if not product.is_published:
raise Http404("Продукт не найден")
return product
def get_breadcrumbs(self):
product = self.object
return [
{'title': 'Продукты', 'url_name': 'products:product_list'},
{
'title': product.category.name,
'url_name': 'products:product_list',
'extra_params': f'?category={product.category.slug}',
},
{'title': product.title, 'url_name': None},
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
product = self.object
context['title'] = product.get_seo_title()
context['meta_description'] = product.get_seo_description()
context['meta_keywords'] = (
f"1С, {product.category.name}, "
f"{', '.join(c.name for c in product.configurations.all())}"
)
# Форма заказа с предзаполнением для авторизованных
initial = {}
if self.request.user.is_authenticated:
user = self.request.user
initial['name'] = user.get_full_name() or user.username
initial['email'] = user.email
# Если есть профиль и телефон
if hasattr(user, 'profile') and user.profile.phone:
initial['phone'] = user.profile.phone
order_form = OrderForm(initial=initial)
order_form.fields['configuration'].queryset = product.configurations.all()
context['order_form'] = order_form
form = CallbackForm()
if self.request.user.is_authenticated:
if 'captcha' in form.fields:
del form.fields['captcha']
context.update({
'form': form,
})
return context
@method_decorator(staff_member_required, name='dispatch')
class ProductDraftPreviewView(DetailView):
model = Product
template_name = 'products/product_detail.html'
context_object_name = 'product'
def get_queryset(self):
# Показываем все продукты (включая неопубликованные) только для персонала
return Product.objects.all()
def order_create(request, slug):
product = get_object_or_404(Product, slug=slug, is_published=True)
if request.method == 'POST':
form = OrderForm(request.POST)
# Переопределяем queryset для поля configuration только те, что связаны с продуктом
form.fields['configuration'].queryset = product.configurations.all()
if form.is_valid():
order = form.save(commit=False)
order.product = product
# Если пользователь авторизован, связываем заказ с ним
if request.user.is_authenticated:
order.user = request.user
# Можно предзаполнить имя и email из профиля, если они пустые в форме
if not order.name:
order.name = request.user.get_full_name() or request.user.username
if not order.email:
order.email = request.user.email
order.save()
# Сохраняем выбранную конфигурацию (уже сохранена в форме)
# 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)
else:
for field, errors in form.errors.items():
for error in errors:
messages.error(request, f'❌ Ошибка в поле "{field}": {error}')
return redirect('products:product_detail', slug=slug)