slugify service

This commit is contained in:
Tobias Brunner 2025-01-27 17:00:56 +01:00
parent 483f076d1a
commit 273e417da2
No known key found for this signature in database
8 changed files with 79 additions and 15 deletions

View file

@ -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):

View file

@ -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),
),
]

View file

@ -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)

View file

@ -67,7 +67,7 @@
<div class="mt-4">
<button type="submit" class="btn btn-primary">Submit</button>
<a href="{% url 'services:service_detail' service.id %}" class="btn btn-secondary">Cancel</a>
<a href="{% url 'services:service_detail' service.slug %}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>

View file

@ -59,7 +59,7 @@
</div>
</div>
<a href="{% url 'services:create_lead' service.id %}" class="btn btn-success">Show Interest</a>
<a href="{% url 'services:create_lead' service.slug %}" class="btn btn-success">Show Interest</a>
<a href="{% url 'services:service_list' %}" class="btn btn-secondary">Back to Services</a>
</div>
</div>

View file

@ -112,8 +112,8 @@
Price: ${{ service.price }}
</small>
</p>
<a href="{% url 'services:service_detail' service.pk %}" class="btn btn-primary">View Details</a>
<a href="{% url 'services:create_lead' service.id %}" class="btn btn-success">Show Interest</a>
<a href="{{ service.get_absolute_url }}" class="btn btn-primary">View Details</a>
<a href="{% url 'services:create_lead' service.slug %}" class="btn btn-success">Show Interest</a>
</div>
</div>
</div>

View file

@ -5,8 +5,8 @@ app_name = "services"
urlpatterns = [
path("", views.service_list, name="service_list"),
path("service/<int:pk>/", views.service_detail, name="service_detail"),
path("service/<int:service_id>/interest/", views.create_lead, name="create_lead"),
path("service/<int:service_id>/thank-you/", views.thank_you, name="thank_you"),
path("service/<slug:slug>/", views.service_detail, name="service_detail"),
path("service/<slug:slug>/interest/", views.create_lead, name="create_lead"),
path("service/<slug:slug>/thank-you/", views.thank_you, name="thank_you"),
path("provider/<slug:slug>/", views.provider_detail, name="provider_detail"),
]

View file

@ -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)