Files
igny8/backend/igny8_core/modules/planner/serializers.py
2025-11-19 20:53:29 +05:00

242 lines
9.5 KiB
Python

from rest_framework import serializers
from django.conf import settings
from .models import Keywords, Clusters, ContentIdeas
from igny8_core.auth.models import SeedKeyword
from igny8_core.auth.serializers import SeedKeywordSerializer
from igny8_core.business.site_building.models import SiteBlueprintTaxonomy
class KeywordSerializer(serializers.ModelSerializer):
"""Serializer for Keywords model with SeedKeyword relationship"""
# Read-only properties from seed_keyword
keyword = serializers.CharField(read_only=True) # From seed_keyword.keyword
volume = serializers.IntegerField(read_only=True) # From seed_keyword.volume or volume_override
difficulty = serializers.IntegerField(read_only=True) # From seed_keyword.difficulty or difficulty_override
intent = serializers.CharField(read_only=True) # From seed_keyword.intent
# SeedKeyword relationship
# Required for create, optional for update (can change seed_keyword or just update other fields)
seed_keyword_id = serializers.IntegerField(write_only=True, required=False)
seed_keyword = SeedKeywordSerializer(read_only=True)
# Overrides
volume_override = serializers.IntegerField(required=False, allow_null=True)
difficulty_override = serializers.IntegerField(required=False, allow_null=True)
# Related fields
cluster_name = serializers.SerializerMethodField()
sector_name = serializers.SerializerMethodField()
site_id = serializers.IntegerField(write_only=True, required=False)
sector_id = serializers.IntegerField(write_only=True, required=False)
class Meta:
model = Keywords
fields = [
'id',
'seed_keyword_id',
'seed_keyword',
'keyword',
'volume',
'difficulty',
'intent',
'volume_override',
'difficulty_override',
'cluster_id',
'cluster_name',
'sector_name',
'status',
'created_at',
'updated_at',
'site_id',
'sector_id',
'account_id',
]
read_only_fields = ['id', 'created_at', 'updated_at', 'account_id', 'keyword', 'volume', 'difficulty', 'intent']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Only include Stage 1 fields when feature flag is enabled
if getattr(settings, 'USE_SITE_BUILDER_REFACTOR', False):
self.fields['attribute_values'] = serializers.JSONField(read_only=True)
def validate(self, attrs):
"""Validate that seed_keyword_id is provided for create operations"""
# For create operations, seed_keyword_id is required
if self.instance is None and 'seed_keyword_id' not in attrs:
raise serializers.ValidationError({'seed_keyword_id': 'This field is required when creating a keyword.'})
return attrs
def create(self, validated_data):
"""Create Keywords instance with seed_keyword"""
seed_keyword_id = validated_data.pop('seed_keyword_id', None)
if not seed_keyword_id:
raise serializers.ValidationError({'seed_keyword_id': 'This field is required when creating a keyword.'})
try:
seed_keyword = SeedKeyword.objects.get(id=seed_keyword_id)
except SeedKeyword.DoesNotExist:
raise serializers.ValidationError({'seed_keyword_id': f'SeedKeyword with id {seed_keyword_id} does not exist'})
validated_data['seed_keyword'] = seed_keyword
return super().create(validated_data)
def update(self, instance, validated_data):
"""Update Keywords instance with seed_keyword"""
# seed_keyword_id is optional for updates - only update if provided
if 'seed_keyword_id' in validated_data:
seed_keyword_id = validated_data.pop('seed_keyword_id')
try:
seed_keyword = SeedKeyword.objects.get(id=seed_keyword_id)
validated_data['seed_keyword'] = seed_keyword
except SeedKeyword.DoesNotExist:
raise serializers.ValidationError({'seed_keyword_id': f'SeedKeyword with id {seed_keyword_id} does not exist'})
return super().update(instance, validated_data)
def get_cluster_name(self, obj):
"""Get cluster name from Clusters model"""
if obj.cluster_id:
try:
cluster = Clusters.objects.get(id=obj.cluster_id)
return cluster.name
except Clusters.DoesNotExist:
return None
return None
def get_sector_name(self, obj):
"""Get sector name from Sector model"""
if obj.sector_id:
try:
from igny8_core.auth.models import Sector
sector = Sector.objects.get(id=obj.sector_id)
return sector.name
except Sector.DoesNotExist:
return None
return None
class ClusterSerializer(serializers.ModelSerializer):
"""Serializer for Clusters model"""
sector_name = serializers.SerializerMethodField()
site_id = serializers.IntegerField(write_only=True, required=False)
sector_id = serializers.IntegerField(write_only=True, required=False)
class Meta:
model = Clusters
fields = [
'id',
'name',
'description',
'keywords_count',
'volume',
'mapped_pages',
'status',
'sector_name',
'created_at',
'updated_at',
'site_id',
'sector_id',
'account_id',
]
read_only_fields = ['id', 'created_at', 'updated_at', 'account_id', 'keywords_count', 'volume', 'mapped_pages']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Only include Stage 1 fields when feature flag is enabled
if getattr(settings, 'USE_SITE_BUILDER_REFACTOR', False):
self.fields['context_type'] = serializers.CharField(read_only=True)
self.fields['context_type_display'] = serializers.SerializerMethodField()
self.fields['dimension_meta'] = serializers.JSONField(read_only=True)
def get_sector_name(self, obj):
"""Get sector name from Sector model"""
if obj.sector_id:
try:
from igny8_core.auth.models import Sector
sector = Sector.objects.get(id=obj.sector_id)
return sector.name
except Sector.DoesNotExist:
return None
return None
def get_context_type_display(self, obj):
"""Get context type display name (only when feature flag enabled)"""
if hasattr(obj, 'get_context_type_display'):
return obj.get_context_type_display()
return None
def validate_name(self, value):
"""Ensure cluster name is unique within account"""
# Uniqueness is handled at model level, but we can add additional validation here
return value
class ContentIdeasSerializer(serializers.ModelSerializer):
"""Serializer for ContentIdeas model"""
keyword_cluster_name = serializers.SerializerMethodField()
sector_name = serializers.SerializerMethodField()
site_id = serializers.IntegerField(write_only=True, required=False)
sector_id = serializers.IntegerField(write_only=True, required=False)
class Meta:
model = ContentIdeas
fields = [
'id',
'idea_title',
'description',
'content_structure',
'content_type',
'target_keywords',
'keyword_cluster_id',
'keyword_cluster_name',
'sector_name',
'status',
'estimated_word_count',
'created_at',
'updated_at',
'site_id',
'sector_id',
'account_id',
]
read_only_fields = ['id', 'created_at', 'updated_at', 'account_id']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Only include Stage 1 fields when feature flag is enabled
if getattr(settings, 'USE_SITE_BUILDER_REFACTOR', False):
self.fields['taxonomy_id'] = serializers.IntegerField(read_only=True, allow_null=True)
self.fields['taxonomy_name'] = serializers.SerializerMethodField()
self.fields['site_entity_type'] = serializers.CharField(read_only=True)
self.fields['cluster_role'] = serializers.CharField(read_only=True)
def get_keyword_cluster_name(self, obj):
"""Get cluster name from Clusters model"""
if obj.keyword_cluster_id:
try:
cluster = Clusters.objects.get(id=obj.keyword_cluster_id)
return cluster.name
except Clusters.DoesNotExist:
return None
return None
def get_sector_name(self, obj):
"""Get sector name from Sector model"""
if obj.sector_id:
try:
from igny8_core.auth.models import Sector
sector = Sector.objects.get(id=obj.sector_id)
return sector.name
except Sector.DoesNotExist:
return None
return None
def get_taxonomy_name(self, obj):
if obj.taxonomy_id:
try:
taxonomy = SiteBlueprintTaxonomy.objects.get(id=obj.taxonomy_id)
return taxonomy.name
except SiteBlueprintTaxonomy.DoesNotExist:
return None
return None