Enhance Content Management with New Taxonomy and Attribute Models
- Introduced `ContentTaxonomy` and `ContentAttribute` models for improved content categorization and attribute management. - Updated `Content` model to support new fields for content format, cluster role, and external type. - Refactored serializers and views to accommodate new models, including `ContentTaxonomySerializer` and `ContentAttributeSerializer`. - Added new API endpoints for managing taxonomies and attributes, enhancing the content management capabilities. - Updated admin interfaces for `Content`, `ContentTaxonomy`, and `ContentAttribute` to reflect new structures and improve usability. - Implemented backward compatibility for existing attribute mappings. - Enhanced filtering and search capabilities in the API for better content retrieval.
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
# Generated by Django 5.2.8 on 2025-11-21 17:48
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('igny8_core_auth', '0002_add_wp_api_key_to_site'),
|
||||
('planner', '0002_initial'),
|
||||
('writer', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='contentattributemap',
|
||||
name='account',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contentattributemap',
|
||||
name='content',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contentattributemap',
|
||||
name='sector',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contentattributemap',
|
||||
name='site',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contentattributemap',
|
||||
name='task',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='cluster',
|
||||
field=models.ForeignKey(blank=True, help_text='Primary semantic cluster', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='contents', to='planner.clusters'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='cluster_role',
|
||||
field=models.CharField(blank=True, choices=[('hub', 'Hub Page'), ('supporting', 'Supporting Content'), ('attribute', 'Attribute Page')], db_index=True, default='supporting', help_text='Role within cluster strategy', max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='content_format',
|
||||
field=models.CharField(blank=True, choices=[('article', 'Article'), ('listicle', 'Listicle'), ('guide', 'How-To Guide'), ('comparison', 'Comparison'), ('review', 'Review'), ('roundup', 'Roundup')], db_index=True, help_text='Content format (only for entity_type=post)', max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='external_type',
|
||||
field=models.CharField(blank=True, help_text='WordPress post type (post, page, product, service)', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='content',
|
||||
name='entity_type',
|
||||
field=models.CharField(choices=[('post', 'Blog Post'), ('page', 'Page'), ('product', 'Product'), ('service', 'Service Page'), ('taxonomy_term', 'Taxonomy Term Page'), ('blog_post', 'Blog Post (Legacy)'), ('article', 'Article (Legacy)'), ('taxonomy', 'Taxonomy Page (Legacy)')], db_index=True, default='post', help_text='Type of content entity', max_length=50),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ContentAttribute',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('attribute_type', models.CharField(choices=[('product_spec', 'Product Specification'), ('service_modifier', 'Service Modifier'), ('semantic_facet', 'Semantic Facet')], db_index=True, default='product_spec', help_text='Type of attribute', max_length=50)),
|
||||
('name', models.CharField(help_text='Attribute name (e.g., Color, Material)', max_length=120)),
|
||||
('value', models.CharField(blank=True, help_text='Attribute value (e.g., Blue, Cotton)', max_length=255, null=True)),
|
||||
('external_id', models.IntegerField(blank=True, help_text='WP attribute term ID', null=True)),
|
||||
('external_attribute_name', models.CharField(blank=True, help_text='WP attribute slug (e.g., pa_color, pa_size)', max_length=100)),
|
||||
('source', models.CharField(choices=[('blueprint', 'Blueprint'), ('manual', 'Manual'), ('import', 'Import'), ('wordpress', 'WordPress')], default='manual', max_length=50)),
|
||||
('metadata', models.JSONField(blank=True, default=dict, help_text='Additional metadata')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.account')),
|
||||
('cluster', models.ForeignKey(blank=True, help_text='Optional cluster association for semantic attributes', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='attributes', to='planner.clusters')),
|
||||
('content', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to='writer.content')),
|
||||
('sector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.sector')),
|
||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.site')),
|
||||
('task', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='attribute_mappings', to='writer.tasks')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Content Attribute',
|
||||
'verbose_name_plural': 'Content Attributes',
|
||||
'db_table': 'igny8_content_attributes',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ContentTaxonomy',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(db_index=True, help_text='Term name', max_length=255)),
|
||||
('slug', models.SlugField(help_text='URL slug', max_length=255)),
|
||||
('taxonomy_type', models.CharField(choices=[('category', 'Category'), ('tag', 'Tag'), ('product_cat', 'Product Category'), ('product_tag', 'Product Tag'), ('product_attr', 'Product Attribute'), ('service_cat', 'Service Category')], db_index=True, help_text='Type of taxonomy', max_length=50)),
|
||||
('description', models.TextField(blank=True, help_text='Term description')),
|
||||
('external_id', models.IntegerField(blank=True, db_index=True, help_text='WordPress term ID', null=True)),
|
||||
('external_taxonomy', models.CharField(blank=True, help_text='WP taxonomy name (category, post_tag, product_cat, pa_color)', max_length=100)),
|
||||
('sync_status', models.CharField(choices=[('native', 'Native IGNY8'), ('imported', 'Imported from External'), ('synced', 'Synced with External')], db_index=True, default='native', help_text='Sync status with external system', max_length=50)),
|
||||
('count', models.IntegerField(default=0, help_text='Post/product count from WordPress')),
|
||||
('metadata', models.JSONField(blank=True, default=dict, help_text='Additional metadata')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.account')),
|
||||
('clusters', models.ManyToManyField(blank=True, help_text='Semantic clusters this term maps to', related_name='taxonomy_terms', to='planner.clusters')),
|
||||
('parent', models.ForeignKey(blank=True, help_text='Parent term for hierarchical taxonomies', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='writer.contenttaxonomy')),
|
||||
('sector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.sector')),
|
||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.site')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Content Taxonomy',
|
||||
'verbose_name_plural': 'Content Taxonomies',
|
||||
'db_table': 'igny8_content_taxonomy_terms',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ContentTaxonomyRelation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.account')),
|
||||
('content', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='taxonomy_relations', to='writer.content')),
|
||||
('sector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.sector')),
|
||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.site')),
|
||||
('taxonomy', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='content_relations', to='writer.contenttaxonomy')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'igny8_content_taxonomy_relations',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='taxonomies',
|
||||
field=models.ManyToManyField(blank=True, help_text='Associated taxonomy terms (categories, tags, attributes)', related_name='contents', through='writer.ContentTaxonomyRelation', to='writer.contenttaxonomy'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['content_format'], name='igny8_conte_content_b538ee_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['cluster_role'], name='igny8_conte_cluster_32e22a_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['cluster'], name='igny8_conte_cluster_e545d1_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['external_type'], name='igny8_conte_externa_a26125_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='content',
|
||||
index=models.Index(fields=['site', 'entity_type'], name='igny8_conte_site_id_e559d5_idx'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='ContentAttributeMap',
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['name'], name='igny8_conte_name_bacaae_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['attribute_type'], name='igny8_conte_attribu_5d6f12_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['content', 'name'], name='igny8_conte_content_6c7c68_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['content', 'attribute_type'], name='igny8_conte_content_91df40_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['cluster', 'attribute_type'], name='igny8_conte_cluster_1f91b7_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contentattribute',
|
||||
index=models.Index(fields=['external_id'], name='igny8_conte_externa_0bf0e8_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['name'], name='igny8_conte_name_f35eea_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['slug'], name='igny8_conte_slug_65c0a2_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['taxonomy_type'], name='igny8_conte_taxonom_04e1c2_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['sync_status'], name='igny8_conte_sync_st_307b43_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['external_id', 'external_taxonomy'], name='igny8_conte_externa_15861e_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['site', 'taxonomy_type'], name='igny8_conte_site_id_6f84b7_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomy',
|
||||
index=models.Index(fields=['site', 'sector'], name='igny8_conte_site_id_9dddc7_idx'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='contenttaxonomy',
|
||||
unique_together={('site', 'external_id', 'external_taxonomy'), ('site', 'slug', 'taxonomy_type')},
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomyrelation',
|
||||
index=models.Index(fields=['content'], name='igny8_conte_content_a897e5_idx'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='contenttaxonomyrelation',
|
||||
index=models.Index(fields=['taxonomy'], name='igny8_conte_taxonom_7091e0_idx'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='contenttaxonomyrelation',
|
||||
unique_together={('content', 'taxonomy')},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.2.8 on 2025-11-21 17:50
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0002_phase1_add_unified_taxonomy_and_attributes'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='contenttaxonomyrelation',
|
||||
name='account',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contenttaxonomyrelation',
|
||||
name='sector',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contenttaxonomyrelation',
|
||||
name='site',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,181 @@
|
||||
# Generated migration for Phase 2 data migration
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def migrate_content_entity_types(apps, schema_editor):
|
||||
"""Migrate legacy entity_type values to new unified structure"""
|
||||
Content = apps.get_model('writer', 'Content')
|
||||
|
||||
# Map legacy entity types to new structure
|
||||
legacy_mapping = {
|
||||
'blog_post': ('post', 'article'),
|
||||
'article': ('post', 'article'),
|
||||
'taxonomy': ('taxonomy_term', None),
|
||||
}
|
||||
|
||||
for content in Content.objects.all():
|
||||
old_type = content.entity_type
|
||||
|
||||
if old_type in legacy_mapping:
|
||||
new_type, format_type = legacy_mapping[old_type]
|
||||
content.entity_type = new_type
|
||||
if format_type and new_type == 'post':
|
||||
content.content_format = format_type
|
||||
content.save(update_fields=['entity_type', 'content_format'])
|
||||
|
||||
|
||||
def migrate_task_entity_types(apps, schema_editor):
|
||||
"""Migrate task entity_type to content when task has associated content"""
|
||||
Content = apps.get_model('writer', 'Content')
|
||||
Tasks = apps.get_model('writer', 'Tasks')
|
||||
|
||||
for task in Tasks.objects.filter(entity_type__isnull=False):
|
||||
try:
|
||||
content = Content.objects.get(task=task)
|
||||
|
||||
# Map task entity_type to content
|
||||
if task.entity_type == 'blog_post':
|
||||
content.entity_type = 'post'
|
||||
content.content_format = 'article'
|
||||
elif task.entity_type == 'article':
|
||||
content.entity_type = 'post'
|
||||
content.content_format = 'article'
|
||||
elif task.entity_type == 'product':
|
||||
content.entity_type = 'product'
|
||||
elif task.entity_type == 'service':
|
||||
content.entity_type = 'service'
|
||||
elif task.entity_type == 'taxonomy':
|
||||
content.entity_type = 'taxonomy_term'
|
||||
elif task.entity_type == 'page':
|
||||
content.entity_type = 'page'
|
||||
|
||||
# Migrate cluster_role from task
|
||||
if task.cluster_role:
|
||||
content.cluster_role = task.cluster_role
|
||||
|
||||
# Migrate cluster relationship
|
||||
if task.cluster_id:
|
||||
content.cluster_id = task.cluster_id
|
||||
|
||||
content.save()
|
||||
except Content.DoesNotExist:
|
||||
pass
|
||||
|
||||
|
||||
def migrate_content_categories_tags_to_taxonomy(apps, schema_editor):
|
||||
"""Migrate JSON categories and tags to ContentTaxonomy M2M"""
|
||||
Content = apps.get_model('writer', 'Content')
|
||||
ContentTaxonomy = apps.get_model('writer', 'ContentTaxonomy')
|
||||
ContentTaxonomyRelation = apps.get_model('writer', 'ContentTaxonomyRelation')
|
||||
|
||||
for content in Content.objects.all():
|
||||
# Skip if no categories or tags
|
||||
if not content.categories and not content.tags:
|
||||
continue
|
||||
|
||||
# Migrate categories (stored as JSON list)
|
||||
if content.categories:
|
||||
for category_name in content.categories:
|
||||
if isinstance(category_name, str) and category_name.strip():
|
||||
# Get or create taxonomy term
|
||||
taxonomy, created = ContentTaxonomy.objects.get_or_create(
|
||||
site=content.site,
|
||||
slug=category_name.lower().replace(' ', '-')[:255],
|
||||
taxonomy_type='category',
|
||||
defaults={
|
||||
'name': category_name[:255],
|
||||
'account': content.account,
|
||||
'sector': content.sector,
|
||||
'sync_status': 'native',
|
||||
}
|
||||
)
|
||||
# Create relation manually
|
||||
ContentTaxonomyRelation.objects.get_or_create(
|
||||
content=content,
|
||||
taxonomy=taxonomy
|
||||
)
|
||||
|
||||
# Migrate tags (stored as JSON list)
|
||||
if content.tags:
|
||||
for tag_name in content.tags:
|
||||
if isinstance(tag_name, str) and tag_name.strip():
|
||||
taxonomy, created = ContentTaxonomy.objects.get_or_create(
|
||||
site=content.site,
|
||||
slug=tag_name.lower().replace(' ', '-')[:255],
|
||||
taxonomy_type='tag',
|
||||
defaults={
|
||||
'name': tag_name[:255],
|
||||
'account': content.account,
|
||||
'sector': content.sector,
|
||||
'sync_status': 'native',
|
||||
}
|
||||
)
|
||||
# Create relation manually
|
||||
ContentTaxonomyRelation.objects.get_or_create(
|
||||
content=content,
|
||||
taxonomy=taxonomy
|
||||
)
|
||||
|
||||
|
||||
def migrate_blueprint_taxonomies(apps, schema_editor):
|
||||
"""Migrate SiteBlueprintTaxonomy to ContentTaxonomy"""
|
||||
try:
|
||||
SiteBlueprintTaxonomy = apps.get_model('site_building', 'SiteBlueprintTaxonomy')
|
||||
ContentTaxonomy = apps.get_model('writer', 'ContentTaxonomy')
|
||||
|
||||
taxonomy_type_mapping = {
|
||||
'blog_category': 'category',
|
||||
'blog_tag': 'tag',
|
||||
'product_category': 'product_cat',
|
||||
'product_tag': 'product_tag',
|
||||
'product_attribute': 'product_attr',
|
||||
'service_category': 'service_cat',
|
||||
}
|
||||
|
||||
for bp_tax in SiteBlueprintTaxonomy.objects.all():
|
||||
new_type = taxonomy_type_mapping.get(bp_tax.taxonomy_type, 'category')
|
||||
|
||||
# Create or update ContentTaxonomy
|
||||
taxonomy, created = ContentTaxonomy.objects.update_or_create(
|
||||
site=bp_tax.site,
|
||||
slug=bp_tax.slug,
|
||||
taxonomy_type=new_type,
|
||||
defaults={
|
||||
'name': bp_tax.name,
|
||||
'description': bp_tax.description or '',
|
||||
'account': bp_tax.account,
|
||||
'sector': bp_tax.sector,
|
||||
'external_id': int(bp_tax.external_reference) if bp_tax.external_reference and bp_tax.external_reference.isdigit() else None,
|
||||
'sync_status': 'imported' if bp_tax.external_reference else 'native',
|
||||
'metadata': bp_tax.metadata if hasattr(bp_tax, 'metadata') else {},
|
||||
}
|
||||
)
|
||||
|
||||
# Migrate cluster relationships
|
||||
if hasattr(bp_tax, 'clusters'):
|
||||
for cluster in bp_tax.clusters.all():
|
||||
taxonomy.clusters.add(cluster)
|
||||
except LookupError:
|
||||
# SiteBlueprintTaxonomy model doesn't exist, skip
|
||||
pass
|
||||
|
||||
|
||||
def reverse_migrations(apps, schema_editor):
|
||||
"""Reverse migration - not implemented as data loss is acceptable"""
|
||||
pass
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0003_phase1b_fix_taxonomy_relation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_content_entity_types, reverse_migrations),
|
||||
migrations.RunPython(migrate_task_entity_types, reverse_migrations),
|
||||
migrations.RunPython(migrate_content_categories_tags_to_taxonomy, reverse_migrations),
|
||||
migrations.RunPython(migrate_blueprint_taxonomies, reverse_migrations),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
# Generated migration for Phase 3 - Mark deprecated fields
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0004_phase2_migrate_data_to_unified_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# Keep deprecated fields for backward compatibility but mark them
|
||||
# We'll remove them in a future migration after ensuring no dependencies
|
||||
|
||||
# Mark old Task fields as deprecated with help_text
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='content',
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="DEPRECATED: Use Content model instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='word_count',
|
||||
field=models.IntegerField(
|
||||
default=0,
|
||||
help_text="DEPRECATED: Use Content.word_count instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='meta_title',
|
||||
field=models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="DEPRECATED: Use Content.meta_title instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='meta_description',
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="DEPRECATED: Use Content.meta_description instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='assigned_post_id',
|
||||
field=models.IntegerField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="DEPRECATED: Use Content.external_id instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='post_url',
|
||||
field=models.URLField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="DEPRECATED: Use Content.external_url instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='entity_type',
|
||||
field=models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
null=True,
|
||||
db_index=True,
|
||||
help_text="DEPRECATED: Use Content.entity_type instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='cluster_role',
|
||||
field=models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="DEPRECATED: Use Content.cluster_role instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='content_structure',
|
||||
field=models.CharField(
|
||||
max_length=50,
|
||||
default='blog_post',
|
||||
help_text="DEPRECATED: Merged into Content.content_format"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tasks',
|
||||
name='content_type',
|
||||
field=models.CharField(
|
||||
max_length=50,
|
||||
default='blog_post',
|
||||
help_text="DEPRECATED: Merged into Content.entity_type + content_format"
|
||||
),
|
||||
),
|
||||
|
||||
# Mark old Content fields as deprecated
|
||||
migrations.AlterField(
|
||||
model_name='content',
|
||||
name='categories',
|
||||
field=models.JSONField(
|
||||
default=list,
|
||||
blank=True,
|
||||
help_text="DEPRECATED: Use Content.taxonomies M2M instead"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='content',
|
||||
name='tags',
|
||||
field=models.JSONField(
|
||||
default=list,
|
||||
blank=True,
|
||||
help_text="DEPRECATED: Use Content.taxonomies M2M instead"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user