refactor-migration again
This commit is contained in:
@@ -11,6 +11,34 @@ class Tasks(SiteSectorBaseModel):
|
||||
('completed', 'Completed'),
|
||||
]
|
||||
|
||||
CONTENT_TYPE_CHOICES = [
|
||||
('post', 'Post'),
|
||||
('page', 'Page'),
|
||||
('product', 'Product'),
|
||||
('taxonomy', 'Taxonomy'),
|
||||
]
|
||||
|
||||
CONTENT_STRUCTURE_CHOICES = [
|
||||
# Post structures
|
||||
('article', 'Article'),
|
||||
('guide', 'Guide'),
|
||||
('comparison', 'Comparison'),
|
||||
('review', 'Review'),
|
||||
('listicle', 'Listicle'),
|
||||
# Page structures
|
||||
('landing_page', 'Landing Page'),
|
||||
('business_page', 'Business Page'),
|
||||
('service_page', 'Service Page'),
|
||||
('general', 'General'),
|
||||
('cluster_hub', 'Cluster Hub'),
|
||||
# Product structures
|
||||
('product_page', 'Product Page'),
|
||||
# Taxonomy structures
|
||||
('category_archive', 'Category Archive'),
|
||||
('tag_archive', 'Tag Archive'),
|
||||
('attribute_archive', 'Attribute Archive'),
|
||||
]
|
||||
|
||||
title = models.CharField(max_length=255, db_index=True)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
cluster = models.ForeignKey(
|
||||
@@ -34,16 +62,18 @@ class Tasks(SiteSectorBaseModel):
|
||||
content_type = models.CharField(
|
||||
max_length=100,
|
||||
db_index=True,
|
||||
help_text="Content type: post, page, product, service, category, tag, etc.",
|
||||
db_column='entity_type',
|
||||
help_text="Content type: post, page, product, taxonomy",
|
||||
choices=CONTENT_TYPE_CHOICES,
|
||||
default='post',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
content_structure = models.CharField(
|
||||
max_length=100,
|
||||
db_index=True,
|
||||
help_text="Content structure/format: article, listicle, guide, comparison, product_page, etc.",
|
||||
db_column='cluster_role',
|
||||
help_text="Content structure: article, guide, comparison, review, listicle, landing_page, etc.",
|
||||
choices=CONTENT_STRUCTURE_CHOICES,
|
||||
default='article',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
@@ -104,9 +134,37 @@ class Content(SiteSectorBaseModel):
|
||||
Final architecture: simplified content management.
|
||||
"""
|
||||
|
||||
CONTENT_TYPE_CHOICES = [
|
||||
('post', 'Post'),
|
||||
('page', 'Page'),
|
||||
('product', 'Product'),
|
||||
('taxonomy', 'Taxonomy'),
|
||||
]
|
||||
|
||||
CONTENT_STRUCTURE_CHOICES = [
|
||||
# Post structures
|
||||
('article', 'Article'),
|
||||
('guide', 'Guide'),
|
||||
('comparison', 'Comparison'),
|
||||
('review', 'Review'),
|
||||
('listicle', 'Listicle'),
|
||||
# Page structures
|
||||
('landing_page', 'Landing Page'),
|
||||
('business_page', 'Business Page'),
|
||||
('service_page', 'Service Page'),
|
||||
('general', 'General'),
|
||||
('cluster_hub', 'Cluster Hub'),
|
||||
# Product structures
|
||||
('product_page', 'Product Page'),
|
||||
# Taxonomy structures
|
||||
('category_archive', 'Category Archive'),
|
||||
('tag_archive', 'Tag Archive'),
|
||||
('attribute_archive', 'Attribute Archive'),
|
||||
]
|
||||
|
||||
# Core content fields
|
||||
title = models.CharField(max_length=255, db_index=True)
|
||||
content_html = models.TextField(help_text="Final HTML content", db_column='html_content')
|
||||
content_html = models.TextField(help_text="Final HTML content")
|
||||
cluster = models.ForeignKey(
|
||||
'planner.Clusters',
|
||||
on_delete=models.SET_NULL,
|
||||
@@ -116,20 +174,18 @@ class Content(SiteSectorBaseModel):
|
||||
help_text="Parent cluster (required)"
|
||||
)
|
||||
content_type = models.CharField(
|
||||
max_length=100,
|
||||
max_length=50,
|
||||
choices=CONTENT_TYPE_CHOICES,
|
||||
default='post',
|
||||
db_index=True,
|
||||
help_text="Content type: post, page, product, service, category, tag, etc.",
|
||||
db_column='entity_type',
|
||||
blank=True,
|
||||
null=True
|
||||
help_text="Content type: post, page, product, taxonomy"
|
||||
)
|
||||
content_structure = models.CharField(
|
||||
max_length=100,
|
||||
max_length=50,
|
||||
choices=CONTENT_STRUCTURE_CHOICES,
|
||||
default='article',
|
||||
db_index=True,
|
||||
help_text="Content structure/format: article, listicle, guide, comparison, product_page, etc.",
|
||||
db_column='cluster_role',
|
||||
blank=True,
|
||||
null=True
|
||||
help_text="Content structure/format based on content type"
|
||||
)
|
||||
|
||||
# Taxonomy relationships
|
||||
|
||||
@@ -146,18 +146,32 @@ class ContentIdeas(SiteSectorBaseModel):
|
||||
('published', 'Published'),
|
||||
]
|
||||
|
||||
SITE_ENTITY_TYPE_CHOICES = [
|
||||
CONTENT_TYPE_CHOICES = [
|
||||
('post', 'Post'),
|
||||
('page', 'Page'),
|
||||
('product', 'Product'),
|
||||
('service', 'Service'),
|
||||
('taxonomy_term', 'Taxonomy Term'),
|
||||
('taxonomy', 'Taxonomy'),
|
||||
]
|
||||
|
||||
CLUSTER_ROLE_CHOICES = [
|
||||
('hub', 'Hub'),
|
||||
('supporting', 'Supporting'),
|
||||
('attribute', 'Attribute'),
|
||||
CONTENT_STRUCTURE_CHOICES = [
|
||||
# Post structures
|
||||
('article', 'Article'),
|
||||
('guide', 'Guide'),
|
||||
('comparison', 'Comparison'),
|
||||
('review', 'Review'),
|
||||
('listicle', 'Listicle'),
|
||||
# Page structures
|
||||
('landing_page', 'Landing Page'),
|
||||
('business_page', 'Business Page'),
|
||||
('service_page', 'Service Page'),
|
||||
('general', 'General'),
|
||||
('cluster_hub', 'Cluster Hub'),
|
||||
# Product structures
|
||||
('product_page', 'Product Page'),
|
||||
# Taxonomy structures
|
||||
('category_archive', 'Category Archive'),
|
||||
('tag_archive', 'Tag Archive'),
|
||||
('attribute_archive', 'Attribute Archive'),
|
||||
]
|
||||
|
||||
idea_title = models.CharField(max_length=255, db_index=True)
|
||||
@@ -187,17 +201,17 @@ class ContentIdeas(SiteSectorBaseModel):
|
||||
)
|
||||
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='new')
|
||||
estimated_word_count = models.IntegerField(default=1000)
|
||||
site_entity_type = models.CharField(
|
||||
content_type = models.CharField(
|
||||
max_length=50,
|
||||
choices=SITE_ENTITY_TYPE_CHOICES,
|
||||
default='page',
|
||||
help_text="Target entity type when promoting idea into tasks/pages"
|
||||
choices=CONTENT_TYPE_CHOICES,
|
||||
default='post',
|
||||
help_text="Content type: post, page, product, taxonomy"
|
||||
)
|
||||
cluster_role = models.CharField(
|
||||
content_structure = models.CharField(
|
||||
max_length=50,
|
||||
choices=CLUSTER_ROLE_CHOICES,
|
||||
default='hub',
|
||||
help_text="Role within the cluster-driven sitemap"
|
||||
choices=CONTENT_STRUCTURE_CHOICES,
|
||||
default='article',
|
||||
help_text="Content structure/format based on content type"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
@@ -212,8 +226,8 @@ class ContentIdeas(SiteSectorBaseModel):
|
||||
models.Index(fields=['idea_title']),
|
||||
models.Index(fields=['status']),
|
||||
models.Index(fields=['keyword_cluster']),
|
||||
models.Index(fields=['site_entity_type']),
|
||||
models.Index(fields=['cluster_role']),
|
||||
models.Index(fields=['content_type']),
|
||||
models.Index(fields=['content_structure']),
|
||||
models.Index(fields=['site', 'sector']),
|
||||
]
|
||||
|
||||
|
||||
@@ -125,10 +125,10 @@ class SitesRendererAdapter(BaseAdapter):
|
||||
# Get blocks from blueprint (placeholders)
|
||||
blocks = page.blocks_json or []
|
||||
page_metadata = {
|
||||
'entity_type': page.entity_type if hasattr(page, 'entity_type') else None,
|
||||
'content_type': page.content_type if hasattr(page, 'content_type') else None,
|
||||
'cluster_id': None,
|
||||
'cluster_name': None,
|
||||
'cluster_role': None,
|
||||
'content_structure': None,
|
||||
'taxonomy_id': None,
|
||||
'taxonomy_name': None,
|
||||
'internal_links': []
|
||||
@@ -178,7 +178,7 @@ class SitesRendererAdapter(BaseAdapter):
|
||||
if cluster_map and cluster_map.cluster:
|
||||
page_metadata['cluster_id'] = cluster_map.cluster.id
|
||||
page_metadata['cluster_name'] = cluster_map.cluster.name
|
||||
page_metadata['cluster_role'] = cluster_map.role or task.cluster_role if task else None
|
||||
page_metadata['content_structure'] = cluster_map.role or task.content_structure if task else None
|
||||
|
||||
# Get taxonomy mapping
|
||||
taxonomy_map = ContentTaxonomyMap.objects.filter(content=content).first()
|
||||
@@ -190,21 +190,21 @@ class SitesRendererAdapter(BaseAdapter):
|
||||
if content.internal_links:
|
||||
page_metadata['internal_links'] = content.internal_links
|
||||
|
||||
# Use content entity_type if available
|
||||
if content.entity_type:
|
||||
page_metadata['entity_type'] = content.entity_type
|
||||
# Use content_type if available
|
||||
if content.content_type:
|
||||
page_metadata['content_type'] = content.content_type
|
||||
|
||||
# Fallback to task metadata if content not found
|
||||
if task and not page_metadata.get('cluster_id'):
|
||||
if task.cluster:
|
||||
page_metadata['cluster_id'] = task.cluster.id
|
||||
page_metadata['cluster_name'] = task.cluster.name
|
||||
page_metadata['cluster_role'] = task.cluster_role
|
||||
page_metadata['content_structure'] = task.content_structure
|
||||
if task.taxonomy:
|
||||
page_metadata['taxonomy_id'] = task.taxonomy.id
|
||||
page_metadata['taxonomy_name'] = task.taxonomy.name
|
||||
if task.entity_type:
|
||||
page_metadata['entity_type'] = task.entity_type
|
||||
if task.content_type:
|
||||
page_metadata['content_type'] = task.content_type
|
||||
|
||||
pages.append({
|
||||
'id': page.id,
|
||||
|
||||
@@ -235,19 +235,19 @@ class PageGenerationService:
|
||||
'contact': 'page',
|
||||
'custom': 'page',
|
||||
}
|
||||
entity_type = entity_type_map.get(page_blueprint.type, 'page')
|
||||
content_type = entity_type_map.get(page_blueprint.type, 'page')
|
||||
|
||||
# Stage 3: Try to find related cluster and taxonomy from blueprint
|
||||
cluster_role = 'hub' # Default
|
||||
# Try to find related cluster and taxonomy from blueprint
|
||||
content_structure = 'article' # Default
|
||||
taxonomy = None
|
||||
|
||||
# Find cluster link for this blueprint to infer role
|
||||
# Find cluster link for this blueprint to infer structure
|
||||
from igny8_core.business.site_building.models import SiteBlueprintCluster
|
||||
cluster_link = SiteBlueprintCluster.objects.filter(
|
||||
site_blueprint=page_blueprint.site_blueprint
|
||||
).first()
|
||||
if cluster_link:
|
||||
cluster_role = cluster_link.role
|
||||
content_structure = cluster_link.role or 'article'
|
||||
|
||||
# Find taxonomy if page type suggests it (products/services)
|
||||
if page_blueprint.type in ['products', 'services']:
|
||||
@@ -264,13 +264,10 @@ class PageGenerationService:
|
||||
title=title,
|
||||
description="\n".join(filter(None, description_parts)),
|
||||
keywords=keywords,
|
||||
content_structure=self._map_content_structure(page_blueprint.type),
|
||||
content_type='article',
|
||||
content_structure=self._map_content_structure(page_blueprint.type) or content_structure,
|
||||
content_type=content_type,
|
||||
status='queued',
|
||||
# Stage 3: Set entity metadata
|
||||
entity_type=entity_type,
|
||||
taxonomy=taxonomy,
|
||||
cluster_role=cluster_role,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
|
||||
Reference in New Issue
Block a user