from django.shortcuts import render, get_object_or_404 from django.db.models import Q from hub.services.models import ( Service, ConsultingPartner, CloudProvider, Category, ) def service_list(request): # Get basic filter parameters search_query = request.GET.get("search", "") category_id = request.GET.get("category", "") consulting_partner_id = request.GET.get("consulting_partner", "") cloud_provider_id = request.GET.get("cloud_provider", "") # Start with all active services # Filter out services with disable_listing=True services = Service.objects.filter(disable_listing=False) # Apply filters based on request parameters if search_query: services = services.filter( Q(name__icontains=search_query) | Q(description__icontains=search_query) ) if category_id: services = services.filter(categories__id=category_id) if consulting_partner_id: services = services.filter(consulting_partners__id=consulting_partner_id) if cloud_provider_id: # Filter through offerings instead of direct cloud_providers relation services = services.filter(offerings__cloud_provider__id=cloud_provider_id) # Order services: featured first, then regular services, then coming soon services = services.order_by( "-is_featured", # Featured first (True before False) "is_coming_soon", # Coming soon last (False before True) "name", # Alphabetically within each group ) # Get all available categories from filtered services available_category_ids = services.values_list( "categories__id", flat=True ).distinct() available_categories = Category.objects.filter( id__in=available_category_ids, parent=None ) # For each parent category, get available children for category in available_categories: child_ids = ( services.filter(categories__parent=category) .values_list("categories__id", flat=True) .distinct() ) category.available_children = Category.objects.filter(id__in=child_ids) # Get available consulting partners from filtered services # Excluding partners with disable_listing=True available_consulting_partner_ids = services.values_list( "consulting_partners__id", flat=True ).distinct() available_consulting_partners = ConsultingPartner.objects.filter( id__in=available_consulting_partner_ids, disable_listing=False ) # Get available cloud providers from filtered services via offerings # Excluding providers with disable_listing=True available_cloud_provider_ids = services.values_list( "offerings__cloud_provider__id", flat=True ).distinct() available_cloud_providers = CloudProvider.objects.filter( id__in=available_cloud_provider_ids, disable_listing=False ) # For the current selection, we need to make sure we include the selected items # even if they don't match other filters if category_id: try: selected_category = Category.objects.get(id=category_id) if selected_category.parent: parent_category = selected_category.parent if parent_category not in available_categories: available_categories = list(available_categories) available_categories.append(parent_category) parent_category.available_children = [selected_category] elif selected_category not in available_categories: available_categories = list(available_categories) available_categories.append(selected_category) except Category.DoesNotExist: pass if consulting_partner_id: try: cp_id = int(consulting_partner_id) if cp_id not in available_consulting_partner_ids: selected_partner = ConsultingPartner.objects.get(id=cp_id) available_consulting_partners = list(available_consulting_partners) available_consulting_partners.append(selected_partner) except (ValueError, ConsultingPartner.DoesNotExist): pass if cloud_provider_id: try: cp_id = int(cloud_provider_id) if cp_id not in available_cloud_provider_ids: selected_provider = CloudProvider.objects.get(id=cp_id) available_cloud_providers = list(available_cloud_providers) available_cloud_providers.append(selected_provider) except (ValueError, CloudProvider.DoesNotExist): pass context = { "services": services, "categories": Category.objects.filter(parent=None), "consulting_partners": ConsultingPartner.objects.filter(disable_listing=False), "cloud_providers": CloudProvider.objects.filter(disable_listing=False), "available_categories": available_categories, "available_consulting_partners": available_consulting_partners, "available_cloud_providers": available_cloud_providers, } return render(request, "services/service_list.html", context) def service_detail(request, slug): service = get_object_or_404( Service.objects.prefetch_related( "categories", "offerings", "offerings__cloud_provider", "offerings__plans", "consulting_partners", "external_links", ), slug=slug, ) context = { "service": service, } return render(request, "services/service_detail.html", context)