slugify service
This commit is contained in:
parent
483f076d1a
commit
273e417da2
8 changed files with 79 additions and 15 deletions
|
@ -42,6 +42,7 @@ class ServiceLevelAdmin(admin.ModelAdmin):
|
||||||
class ServiceAdmin(admin.ModelAdmin):
|
class ServiceAdmin(admin.ModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
"name",
|
"name",
|
||||||
|
"slug",
|
||||||
"cloud_provider",
|
"cloud_provider",
|
||||||
"service_level",
|
"service_level",
|
||||||
"price",
|
"price",
|
||||||
|
@ -49,7 +50,8 @@ class ServiceAdmin(admin.ModelAdmin):
|
||||||
"category_list",
|
"category_list",
|
||||||
)
|
)
|
||||||
list_filter = ("cloud_provider", "service_level", "countries", "categories")
|
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")
|
filter_horizontal = ("countries", "categories")
|
||||||
|
|
||||||
def logo_preview(self, obj):
|
def logo_preview(self, obj):
|
||||||
|
|
44
hub/services/migrations/0006_service_slug.py
Normal file
44
hub/services/migrations/0006_service_slug.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,5 +1,6 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from django_prose_editor.fields import ProseEditorField
|
from django_prose_editor.fields import ProseEditorField
|
||||||
|
@ -89,6 +90,7 @@ class ServiceLevel(models.Model):
|
||||||
|
|
||||||
class Service(models.Model):
|
class Service(models.Model):
|
||||||
name = models.CharField(max_length=200)
|
name = models.CharField(max_length=200)
|
||||||
|
slug = models.SlugField(max_length=250, unique=True)
|
||||||
description = ProseEditorField()
|
description = ProseEditorField()
|
||||||
cloud_provider = models.ForeignKey(CloudProvider, on_delete=models.CASCADE)
|
cloud_provider = models.ForeignKey(CloudProvider, on_delete=models.CASCADE)
|
||||||
service_level = models.ForeignKey(ServiceLevel, on_delete=models.CASCADE)
|
service_level = models.ForeignKey(ServiceLevel, on_delete=models.CASCADE)
|
||||||
|
@ -108,6 +110,22 @@ class Service(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
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):
|
class Lead(models.Model):
|
||||||
service = models.ForeignKey(Service, on_delete=models.CASCADE)
|
service = models.ForeignKey(Service, on_delete=models.CASCADE)
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<button type="submit" class="btn btn-primary">Submit</button>
|
<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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
</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>
|
<a href="{% url 'services:service_list' %}" class="btn btn-secondary">Back to Services</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -112,8 +112,8 @@
|
||||||
Price: ${{ service.price }}
|
Price: ${{ service.price }}
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
<a href="{% url 'services:service_detail' service.pk %}" class="btn btn-primary">View Details</a>
|
<a href="{{ service.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,8 +5,8 @@ app_name = "services"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.service_list, name="service_list"),
|
path("", views.service_list, name="service_list"),
|
||||||
path("service/<int:pk>/", views.service_detail, name="service_detail"),
|
path("service/<slug:slug>/", views.service_detail, name="service_detail"),
|
||||||
path("service/<int:service_id>/interest/", views.create_lead, name="create_lead"),
|
path("service/<slug:slug>/interest/", views.create_lead, name="create_lead"),
|
||||||
path("service/<int:service_id>/thank-you/", views.thank_you, name="thank_you"),
|
path("service/<slug:slug>/thank-you/", views.thank_you, name="thank_you"),
|
||||||
path("provider/<slug:slug>/", views.provider_detail, name="provider_detail"),
|
path("provider/<slug:slug>/", views.provider_detail, name="provider_detail"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -55,8 +55,8 @@ def service_list(request):
|
||||||
return render(request, "services/service_list.html", context)
|
return render(request, "services/service_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
def service_detail(request, pk):
|
def service_detail(request, slug):
|
||||||
service = get_object_or_404(Service, pk=pk)
|
service = get_object_or_404(Service, slug=slug)
|
||||||
return render(request, "services/service_detail.html", {"service": service})
|
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)
|
return render(request, "services/provider_detail.html", context)
|
||||||
|
|
||||||
|
|
||||||
def thank_you(request, service_id):
|
def thank_you(request, slug):
|
||||||
service = get_object_or_404(Service, id=service_id)
|
service = get_object_or_404(Service, slug=slug)
|
||||||
return render(request, "services/thank_you.html", {"service": service})
|
return render(request, "services/thank_you.html", {"service": service})
|
||||||
|
|
||||||
|
|
||||||
def create_lead(request, service_id):
|
def create_lead(request, slug):
|
||||||
service = get_object_or_404(Service, id=service_id)
|
service = get_object_or_404(Service, slug=slug)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = LeadForm(request.POST)
|
form = LeadForm(request.POST)
|
||||||
|
@ -92,7 +92,7 @@ def create_lead(request, service_id):
|
||||||
lead.save()
|
lead.save()
|
||||||
|
|
||||||
logger.info(f"Successfully created lead with Odoo ID: {odoo_lead_id}")
|
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:
|
except Exception as e:
|
||||||
logger.error(f"Failed to create lead: {str(e)}", exc_info=True)
|
logger.error(f"Failed to create lead: {str(e)}", exc_info=True)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue