94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
from django.db import models
|
|
from django.urls import reverse
|
|
from django.utils.text import slugify
|
|
from django.contrib.auth.models import User
|
|
from django_prose_editor.fields import ProseEditorField
|
|
from .base import validate_image_size
|
|
from .services import Service
|
|
from .providers import CloudProvider, ConsultingPartner
|
|
|
|
|
|
class Article(models.Model):
|
|
title = models.CharField(max_length=200)
|
|
slug = models.SlugField(max_length=250, unique=True)
|
|
excerpt = models.TextField(
|
|
max_length=500, help_text="Brief description of the article"
|
|
)
|
|
content = ProseEditorField()
|
|
meta_keywords = models.CharField(
|
|
max_length=255, blank=True, help_text="SEO keywords separated by commas"
|
|
)
|
|
image = models.ImageField(
|
|
upload_to="article_images/",
|
|
help_text="Title picture for the article",
|
|
)
|
|
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="articles")
|
|
|
|
# Relations to other models
|
|
related_service = models.ForeignKey(
|
|
Service,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="articles",
|
|
help_text="Link this article to a specific service",
|
|
)
|
|
related_consulting_partner = models.ForeignKey(
|
|
ConsultingPartner,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="articles",
|
|
help_text="Link this article to a consulting partner",
|
|
)
|
|
related_cloud_provider = models.ForeignKey(
|
|
CloudProvider,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="articles",
|
|
help_text="Link this article to a cloud provider",
|
|
)
|
|
|
|
# Publishing controls
|
|
is_published = models.BooleanField(
|
|
default=False, help_text="Only published articles are visible to users"
|
|
)
|
|
is_featured = models.BooleanField(
|
|
default=False, help_text="Featured articles appear prominently in listings"
|
|
)
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ["-created_at"]
|
|
verbose_name = "Article"
|
|
verbose_name_plural = "Articles"
|
|
|
|
def __str__(self):
|
|
return self.title
|
|
|
|
def save(self, *args, **kwargs):
|
|
# Auto-generate slug from title if not provided
|
|
if not self.slug:
|
|
self.slug = slugify(self.title)
|
|
counter = 1
|
|
while Article.objects.filter(slug=self.slug).exists():
|
|
self.slug = f"{slugify(self.title)}-{counter}"
|
|
counter += 1
|
|
super().save(*args, **kwargs)
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("services:article_detail", kwargs={"slug": self.slug})
|
|
|
|
@property
|
|
def related_to(self):
|
|
"""Returns a string describing what this article is related to"""
|
|
if self.related_service:
|
|
return f"Service: {self.related_service.name}"
|
|
elif self.related_consulting_partner:
|
|
return f"Partner: {self.related_consulting_partner.name}"
|
|
elif self.related_cloud_provider:
|
|
return f"Provider: {self.related_cloud_provider.name}"
|
|
return "General"
|