phase 8
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Generated manually for Phase 8: Universal Content Types
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0008_add_site_structure_generation_prompt_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='aiprompt',
|
||||
name='prompt_type',
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
('clustering', 'Clustering'),
|
||||
('ideas', 'Ideas Generation'),
|
||||
('content_generation', 'Content Generation'),
|
||||
('image_prompt_extraction', 'Image Prompt Extraction'),
|
||||
('image_prompt_template', 'Image Prompt Template'),
|
||||
('negative_prompt', 'Negative Prompt'),
|
||||
('site_structure_generation', 'Site Structure Generation'),
|
||||
('product_generation', 'Product Content Generation'),
|
||||
('service_generation', 'Service Page Generation'),
|
||||
('taxonomy_generation', 'Taxonomy Generation'),
|
||||
],
|
||||
db_index=True,
|
||||
max_length=50
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -21,6 +21,10 @@ class AIPrompt(AccountBaseModel):
|
||||
('image_prompt_template', 'Image Prompt Template'),
|
||||
('negative_prompt', 'Negative Prompt'),
|
||||
('site_structure_generation', 'Site Structure Generation'), # Phase 7: Site Builder prompts
|
||||
# Phase 8: Universal Content Types
|
||||
('product_generation', 'Product Content Generation'),
|
||||
('service_generation', 'Service Page Generation'),
|
||||
('taxonomy_generation', 'Taxonomy Generation'),
|
||||
]
|
||||
|
||||
prompt_type = models.CharField(max_length=50, choices=PROMPT_TYPE_CHOICES, db_index=True)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Generated manually for Phase 8: Universal Content Types
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0010_make_content_task_nullable'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='entity_type',
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
('blog_post', 'Blog Post'),
|
||||
('article', 'Article'),
|
||||
('product', 'Product'),
|
||||
('service', 'Service Page'),
|
||||
('taxonomy', 'Taxonomy Page'),
|
||||
('page', 'Page'),
|
||||
],
|
||||
db_index=True,
|
||||
default='blog_post',
|
||||
help_text='Type of content entity',
|
||||
max_length=50
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='json_blocks',
|
||||
field=models.JSONField(
|
||||
blank=True,
|
||||
default=list,
|
||||
help_text='Structured content blocks (for products, services, taxonomies)'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='structure_data',
|
||||
field=models.JSONField(
|
||||
blank=True,
|
||||
default=dict,
|
||||
help_text='Content structure data (metadata, schema, etc.)'
|
||||
),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['entity_type'], name='igny8_conte_entity__idx'),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -217,6 +217,10 @@ class ContentSerializer(serializers.ModelSerializer):
|
||||
'account_id',
|
||||
'has_image_prompts',
|
||||
'has_generated_images',
|
||||
# Phase 8: Universal Content Types
|
||||
'entity_type',
|
||||
'json_blocks',
|
||||
'structure_data',
|
||||
]
|
||||
read_only_fields = ['id', 'generated_at', 'updated_at', 'account_id']
|
||||
|
||||
|
||||
@@ -757,4 +757,252 @@ class ContentViewSet(SiteSectorModelViewSet):
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
@action(detail=False, methods=['post'], url_path='generate_product', url_name='generate_product')
|
||||
def generate_product(self, request):
|
||||
"""
|
||||
Generate product content (Phase 8).
|
||||
|
||||
POST /api/v1/writer/content/generate_product/
|
||||
{
|
||||
"name": "Product Name",
|
||||
"description": "Product description",
|
||||
"features": ["Feature 1", "Feature 2"],
|
||||
"target_audience": "Target audience",
|
||||
"primary_keyword": "Primary keyword",
|
||||
"site_id": 1, // optional
|
||||
"sector_id": 1 // optional
|
||||
}
|
||||
"""
|
||||
from igny8_core.business.content.services.content_generation_service import ContentGenerationService
|
||||
from igny8_core.auth.models import Site, Sector
|
||||
|
||||
account = getattr(request, 'account', None)
|
||||
if not account:
|
||||
return error_response(
|
||||
error='Account not found',
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
request=request
|
||||
)
|
||||
|
||||
product_data = request.data
|
||||
site_id = product_data.get('site_id')
|
||||
sector_id = product_data.get('sector_id')
|
||||
|
||||
site = None
|
||||
sector = None
|
||||
|
||||
if site_id:
|
||||
try:
|
||||
site = Site.objects.get(id=site_id, account=account)
|
||||
except Site.DoesNotExist:
|
||||
return error_response(
|
||||
error='Site not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
if sector_id:
|
||||
try:
|
||||
sector = Sector.objects.get(id=sector_id, account=account)
|
||||
except Sector.DoesNotExist:
|
||||
return error_response(
|
||||
error='Sector not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
service = ContentGenerationService()
|
||||
|
||||
try:
|
||||
result = service.generate_product_content(
|
||||
product_data=product_data,
|
||||
account=account,
|
||||
site=site,
|
||||
sector=sector
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
return success_response(
|
||||
data={'task_id': result.get('task_id')},
|
||||
message=result.get('message', 'Product content generation started'),
|
||||
request=request
|
||||
)
|
||||
else:
|
||||
return error_response(
|
||||
error=result.get('error', 'Product content generation failed'),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
except Exception as e:
|
||||
return error_response(
|
||||
error=str(e),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
@action(detail=False, methods=['post'], url_path='generate_service', url_name='generate_service')
|
||||
def generate_service(self, request):
|
||||
"""
|
||||
Generate service page content (Phase 8).
|
||||
|
||||
POST /api/v1/writer/content/generate_service/
|
||||
{
|
||||
"name": "Service Name",
|
||||
"description": "Service description",
|
||||
"benefits": ["Benefit 1", "Benefit 2"],
|
||||
"target_audience": "Target audience",
|
||||
"primary_keyword": "Primary keyword",
|
||||
"site_id": 1, // optional
|
||||
"sector_id": 1 // optional
|
||||
}
|
||||
"""
|
||||
from igny8_core.business.content.services.content_generation_service import ContentGenerationService
|
||||
from igny8_core.auth.models import Site, Sector
|
||||
|
||||
account = getattr(request, 'account', None)
|
||||
if not account:
|
||||
return error_response(
|
||||
error='Account not found',
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
request=request
|
||||
)
|
||||
|
||||
service_data = request.data
|
||||
site_id = service_data.get('site_id')
|
||||
sector_id = service_data.get('sector_id')
|
||||
|
||||
site = None
|
||||
sector = None
|
||||
|
||||
if site_id:
|
||||
try:
|
||||
site = Site.objects.get(id=site_id, account=account)
|
||||
except Site.DoesNotExist:
|
||||
return error_response(
|
||||
error='Site not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
if sector_id:
|
||||
try:
|
||||
sector = Sector.objects.get(id=sector_id, account=account)
|
||||
except Sector.DoesNotExist:
|
||||
return error_response(
|
||||
error='Sector not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
service = ContentGenerationService()
|
||||
|
||||
try:
|
||||
result = service.generate_service_page(
|
||||
service_data=service_data,
|
||||
account=account,
|
||||
site=site,
|
||||
sector=sector
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
return success_response(
|
||||
data={'task_id': result.get('task_id')},
|
||||
message=result.get('message', 'Service page generation started'),
|
||||
request=request
|
||||
)
|
||||
else:
|
||||
return error_response(
|
||||
error=result.get('error', 'Service page generation failed'),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
except Exception as e:
|
||||
return error_response(
|
||||
error=str(e),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
@action(detail=False, methods=['post'], url_path='generate_taxonomy', url_name='generate_taxonomy')
|
||||
def generate_taxonomy(self, request):
|
||||
"""
|
||||
Generate taxonomy page content (Phase 8).
|
||||
|
||||
POST /api/v1/writer/content/generate_taxonomy/
|
||||
{
|
||||
"name": "Taxonomy Name",
|
||||
"description": "Taxonomy description",
|
||||
"items": ["Item 1", "Item 2"],
|
||||
"primary_keyword": "Primary keyword",
|
||||
"site_id": 1, // optional
|
||||
"sector_id": 1 // optional
|
||||
}
|
||||
"""
|
||||
from igny8_core.business.content.services.content_generation_service import ContentGenerationService
|
||||
from igny8_core.auth.models import Site, Sector
|
||||
|
||||
account = getattr(request, 'account', None)
|
||||
if not account:
|
||||
return error_response(
|
||||
error='Account not found',
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
request=request
|
||||
)
|
||||
|
||||
taxonomy_data = request.data
|
||||
site_id = taxonomy_data.get('site_id')
|
||||
sector_id = taxonomy_data.get('sector_id')
|
||||
|
||||
site = None
|
||||
sector = None
|
||||
|
||||
if site_id:
|
||||
try:
|
||||
site = Site.objects.get(id=site_id, account=account)
|
||||
except Site.DoesNotExist:
|
||||
return error_response(
|
||||
error='Site not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
if sector_id:
|
||||
try:
|
||||
sector = Sector.objects.get(id=sector_id, account=account)
|
||||
except Sector.DoesNotExist:
|
||||
return error_response(
|
||||
error='Sector not found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
service = ContentGenerationService()
|
||||
|
||||
try:
|
||||
result = service.generate_taxonomy(
|
||||
taxonomy_data=taxonomy_data,
|
||||
account=account,
|
||||
site=site,
|
||||
sector=sector
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
return success_response(
|
||||
data={'task_id': result.get('task_id')},
|
||||
message=result.get('message', 'Taxonomy generation started'),
|
||||
request=request
|
||||
)
|
||||
else:
|
||||
return error_response(
|
||||
error=result.get('error', 'Taxonomy generation failed'),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
except Exception as e:
|
||||
return error_response(
|
||||
error=str(e),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user