Refactor content status terminology and enhance cluster serializers with idea and content counts
This commit is contained in:
@@ -198,7 +198,7 @@ class GenerateContentFunction(BaseAIFunction):
|
||||
tags = parsed.get('tags', [])
|
||||
categories = parsed.get('categories', [])
|
||||
# Content status should always be 'draft' for newly generated content
|
||||
# Status can only be changed manually to 'review' or 'published'
|
||||
# Status can only be changed manually to 'review' or 'publish'
|
||||
content_status = 'draft'
|
||||
else:
|
||||
# Plain text response (legacy)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Clusters, Keywords
|
||||
from .models import Clusters, Keywords, ContentIdeas
|
||||
from django.db.models import Count, Sum, Avg
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ class ClusterSerializer(serializers.ModelSerializer):
|
||||
volume = serializers.SerializerMethodField()
|
||||
difficulty = serializers.SerializerMethodField()
|
||||
sector_name = serializers.SerializerMethodField()
|
||||
ideas_count = serializers.SerializerMethodField()
|
||||
content_count = serializers.SerializerMethodField()
|
||||
site_id = serializers.IntegerField(write_only=True, required=False)
|
||||
sector_id = serializers.IntegerField(write_only=True, required=False)
|
||||
|
||||
@@ -22,6 +24,8 @@ class ClusterSerializer(serializers.ModelSerializer):
|
||||
'volume',
|
||||
'difficulty',
|
||||
'mapped_pages',
|
||||
'ideas_count',
|
||||
'content_count',
|
||||
'status',
|
||||
'sector_name',
|
||||
'site_id',
|
||||
@@ -89,6 +93,22 @@ class ClusterSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
)
|
||||
return round(result['avg_difficulty'] or 0, 1) # Round to 1 decimal place
|
||||
|
||||
def get_ideas_count(self, obj):
|
||||
"""Count content ideas linked to this cluster"""
|
||||
if hasattr(obj, '_ideas_count'):
|
||||
return obj._ideas_count
|
||||
|
||||
return ContentIdeas.objects.filter(keyword_cluster_id=obj.id).count()
|
||||
|
||||
def get_content_count(self, obj):
|
||||
"""Count generated content items linked to this cluster via tasks"""
|
||||
if hasattr(obj, '_content_count'):
|
||||
return obj._content_count
|
||||
|
||||
from igny8_core.modules.writer.models import Content
|
||||
|
||||
return Content.objects.filter(task__cluster_id=obj.id).count()
|
||||
|
||||
@classmethod
|
||||
def prefetch_keyword_stats(cls, clusters):
|
||||
@@ -137,12 +157,34 @@ class ClusterSerializer(serializers.ModelSerializer):
|
||||
for stat in keyword_stats
|
||||
}
|
||||
|
||||
# Prefetch idea counts
|
||||
idea_counts = (
|
||||
ContentIdeas.objects
|
||||
.filter(keyword_cluster_id__in=cluster_ids)
|
||||
.values('keyword_cluster_id')
|
||||
.annotate(count=Count('id'))
|
||||
)
|
||||
idea_stats = {item['keyword_cluster_id']: item['count'] for item in idea_counts}
|
||||
|
||||
# Prefetch content counts (through writer.Tasks -> Content)
|
||||
from igny8_core.modules.writer.models import Content
|
||||
|
||||
content_counts = (
|
||||
Content.objects
|
||||
.filter(task__cluster_id__in=cluster_ids)
|
||||
.values('task__cluster_id')
|
||||
.annotate(count=Count('id'))
|
||||
)
|
||||
content_stats = {item['task__cluster_id']: item['count'] for item in content_counts}
|
||||
|
||||
# Attach stats to each cluster object
|
||||
for cluster in clusters:
|
||||
cluster_stats = stats_dict.get(cluster.id, {'count': 0, 'volume': 0, 'difficulty': 0})
|
||||
cluster._keywords_count = cluster_stats['count']
|
||||
cluster._volume = cluster_stats['volume']
|
||||
cluster._difficulty = cluster_stats['difficulty']
|
||||
cluster._ideas_count = idea_stats.get(cluster.id, 0)
|
||||
cluster._content_count = content_stats.get(cluster.id, 0)
|
||||
|
||||
return clusters
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def migrate_content_status_forward(apps, schema_editor):
|
||||
Content = apps.get_model('writer', 'Content')
|
||||
Content.objects.filter(status='published').update(status='publish')
|
||||
|
||||
|
||||
def migrate_content_status_backward(apps, schema_editor):
|
||||
Content = apps.get_model('writer', 'Content')
|
||||
Content.objects.filter(status='publish').update(status='published')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='status',
|
||||
field=models.CharField(
|
||||
choices=[('queued', 'Queued'), ('completed', 'Completed')],
|
||||
default='queued',
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='content',
|
||||
name='status',
|
||||
field=models.CharField(
|
||||
choices=[('draft', 'Draft'), ('review', 'Review'), ('publish', 'Publish')],
|
||||
default='draft',
|
||||
help_text='Content workflow status (draft, review, publish)',
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
migrations.RunPython(
|
||||
migrate_content_status_forward,
|
||||
migrate_content_status_backward,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -109,9 +109,9 @@ class Content(SiteSectorBaseModel):
|
||||
STATUS_CHOICES = [
|
||||
('draft', 'Draft'),
|
||||
('review', 'Review'),
|
||||
('published', 'Published'),
|
||||
('publish', 'Publish'),
|
||||
]
|
||||
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='draft', help_text="Content workflow status (draft, review, published)")
|
||||
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='draft', help_text="Content workflow status (draft, review, publish)")
|
||||
generated_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
||||
@@ -263,8 +263,8 @@ class TasksViewSet(SiteSectorModelViewSet):
|
||||
# Tasks module not available - update status only
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
tasks = queryset.filter(id__in=ids, status__in=['queued', 'in_progress'])
|
||||
updated_count = tasks.update(status='draft', content='[AI content generation not available]')
|
||||
tasks = queryset.filter(id__in=ids, status='queued')
|
||||
updated_count = tasks.update(status='completed', content='[AI content generation not available]')
|
||||
|
||||
logger.info(f"auto_generate_content: Updated {updated_count} tasks (AI generation not available)")
|
||||
return Response({
|
||||
|
||||
Reference in New Issue
Block a user