From 273e417da235ccfb83a0ac65f0a6bae41cc92a8b Mon Sep 17 00:00:00 2001
From: Tobias Brunner
Date: Mon, 27 Jan 2025 17:00:56 +0100
Subject: [PATCH] slugify service
---
hub/services/admin.py | 4 +-
hub/services/migrations/0006_service_slug.py | 44 +++++++++++++++++++
hub/services/models.py | 18 ++++++++
.../templates/services/lead_form.html | 2 +-
.../templates/services/service_detail.html | 2 +-
.../templates/services/service_list.html | 4 +-
hub/services/urls.py | 6 +--
hub/services/views.py | 14 +++---
8 files changed, 79 insertions(+), 15 deletions(-)
create mode 100644 hub/services/migrations/0006_service_slug.py
diff --git a/hub/services/admin.py b/hub/services/admin.py
index 2cebb43..8afe9d1 100644
--- a/hub/services/admin.py
+++ b/hub/services/admin.py
@@ -42,6 +42,7 @@ class ServiceLevelAdmin(admin.ModelAdmin):
class ServiceAdmin(admin.ModelAdmin):
list_display = (
"name",
+ "slug",
"cloud_provider",
"service_level",
"price",
@@ -49,7 +50,8 @@ class ServiceAdmin(admin.ModelAdmin):
"category_list",
)
list_filter = ("cloud_provider", "service_level", "countries", "categories")
- search_fields = ("name", "description")
+ search_fields = ("name", "description", "slug")
+ prepopulated_fields = {"slug": ("name",)}
filter_horizontal = ("countries", "categories")
def logo_preview(self, obj):
diff --git a/hub/services/migrations/0006_service_slug.py b/hub/services/migrations/0006_service_slug.py
new file mode 100644
index 0000000..31a2cc6
--- /dev/null
+++ b/hub/services/migrations/0006_service_slug.py
@@ -0,0 +1,44 @@
+# Generated by Django 5.1.5 on 2025-01-27 15:57
+
+from django.db import migrations, models
+from django.utils.text import slugify
+
+
+def generate_service_slugs(apps, schema_editor):
+ Service = apps.get_model("services", "Service")
+
+ for service in Service.objects.all():
+ base_slug = f"{service.name}-{service.cloud_provider.name}"
+ slug = slugify(base_slug)
+
+ counter = 1
+ while Service.objects.filter(slug=slug).exists():
+ slug = f"{slugify(base_slug)}-{counter}"
+ counter += 1
+
+ service.slug = slug
+ service.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("services", "0005_lead"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="service",
+ name="slug",
+ field=models.SlugField(max_length=250, blank=True),
+ preserve_default=False,
+ ),
+ migrations.RunPython(
+ generate_service_slugs, reverse_code=migrations.RunPython.noop
+ ),
+ migrations.AlterField(
+ model_name="service",
+ name="slug",
+ field=models.SlugField(max_length=250, unique=True),
+ ),
+ ]
diff --git a/hub/services/models.py b/hub/services/models.py
index a4f47c4..f6576b3 100644
--- a/hub/services/models.py
+++ b/hub/services/models.py
@@ -1,5 +1,6 @@
from django.db import models
from django.core.exceptions import ValidationError
+from django.urls import reverse
from django.utils.text import slugify
from django_prose_editor.fields import ProseEditorField
@@ -89,6 +90,7 @@ class ServiceLevel(models.Model):
class Service(models.Model):
name = models.CharField(max_length=200)
+ slug = models.SlugField(max_length=250, unique=True)
description = ProseEditorField()
cloud_provider = models.ForeignKey(CloudProvider, on_delete=models.CASCADE)
service_level = models.ForeignKey(ServiceLevel, on_delete=models.CASCADE)
@@ -108,6 +110,22 @@ class Service(models.Model):
def __str__(self):
return self.name
+ def save(self, *args, **kwargs):
+ if not self.slug:
+ base_slug = f"{self.name}-{self.cloud_provider.name}"
+ self.slug = slugify(base_slug)
+
+ # If slug exists, append number
+ counter = 1
+ while Service.objects.filter(slug=self.slug).exists():
+ self.slug = f"{slugify(base_slug)}-{counter}"
+ counter += 1
+
+ super().save(*args, **kwargs)
+
+ def get_absolute_url(self):
+ return reverse("services:service_detail", kwargs={"slug": self.slug})
+
class Lead(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
diff --git a/hub/services/templates/services/lead_form.html b/hub/services/templates/services/lead_form.html
index 32da988..4e1789a 100644
--- a/hub/services/templates/services/lead_form.html
+++ b/hub/services/templates/services/lead_form.html
@@ -67,7 +67,7 @@
diff --git a/hub/services/templates/services/service_detail.html b/hub/services/templates/services/service_detail.html
index 249ada8..923cf5e 100644
--- a/hub/services/templates/services/service_detail.html
+++ b/hub/services/templates/services/service_detail.html
@@ -59,7 +59,7 @@
- Show Interest
+ Show Interest
Back to Services
diff --git a/hub/services/templates/services/service_list.html b/hub/services/templates/services/service_list.html
index 975aa02..852d0c2 100644
--- a/hub/services/templates/services/service_list.html
+++ b/hub/services/templates/services/service_list.html
@@ -112,8 +112,8 @@
Price: ${{ service.price }}
- View Details
- Show Interest
+ View Details
+ Show Interest
diff --git a/hub/services/urls.py b/hub/services/urls.py
index ee5cfb1..c332763 100644
--- a/hub/services/urls.py
+++ b/hub/services/urls.py
@@ -5,8 +5,8 @@ app_name = "services"
urlpatterns = [
path("", views.service_list, name="service_list"),
- path("service//", views.service_detail, name="service_detail"),
- path("service//interest/", views.create_lead, name="create_lead"),
- path("service//thank-you/", views.thank_you, name="thank_you"),
+ path("service//", views.service_detail, name="service_detail"),
+ path("service//interest/", views.create_lead, name="create_lead"),
+ path("service//thank-you/", views.thank_you, name="thank_you"),
path("provider//", views.provider_detail, name="provider_detail"),
]
diff --git a/hub/services/views.py b/hub/services/views.py
index ff25602..981aa78 100644
--- a/hub/services/views.py
+++ b/hub/services/views.py
@@ -55,8 +55,8 @@ def service_list(request):
return render(request, "services/service_list.html", context)
-def service_detail(request, pk):
- service = get_object_or_404(Service, pk=pk)
+def service_detail(request, slug):
+ service = get_object_or_404(Service, slug=slug)
return render(request, "services/service_detail.html", {"service": service})
@@ -70,13 +70,13 @@ def provider_detail(request, slug):
return render(request, "services/provider_detail.html", context)
-def thank_you(request, service_id):
- service = get_object_or_404(Service, id=service_id)
+def thank_you(request, slug):
+ service = get_object_or_404(Service, slug=slug)
return render(request, "services/thank_you.html", {"service": service})
-def create_lead(request, service_id):
- service = get_object_or_404(Service, id=service_id)
+def create_lead(request, slug):
+ service = get_object_or_404(Service, slug=slug)
if request.method == "POST":
form = LeadForm(request.POST)
@@ -92,7 +92,7 @@ def create_lead(request, service_id):
lead.save()
logger.info(f"Successfully created lead with Odoo ID: {odoo_lead_id}")
- return redirect("services:thank_you", service_id=service.id)
+ return redirect("services:thank_you", slug=service.slug)
except Exception as e:
logger.error(f"Failed to create lead: {str(e)}", exc_info=True)