Add validated editorial content schema
This commit is contained in:
168
apps/content/migrations/0001_initial.py
Normal file
168
apps/content/migrations/0001_initial.py
Normal file
@@ -0,0 +1,168 @@
|
||||
# Generated by Django 5.2.5 on 2026-09-27 05:53
|
||||
|
||||
import apps.content.models
|
||||
import apps.content.validators
|
||||
import django.core.validators
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EditorialPage',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('slug', models.CharField(max_length=20, unique=True)),
|
||||
('page_kind', models.CharField(choices=[('sections', 'Sections'), ('listing_intro', 'Listing intro')], max_length=20)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MediaAsset',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('file', models.ImageField(upload_to=apps.content.models.media_path)),
|
||||
('width', models.PositiveIntegerField(default=0)),
|
||||
('height', models.PositiveIntegerField(default=0)),
|
||||
('bytes', models.PositiveIntegerField(default=0)),
|
||||
('alt', models.CharField(max_length=180)),
|
||||
('source', models.CharField(max_length=300)),
|
||||
('license', models.CharField(max_length=200)),
|
||||
('approved', models.BooleanField(default=False)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SiteIdentity',
|
||||
fields=[
|
||||
('id', models.PositiveSmallIntegerField(default=1, editable=False, primary_key=True, serialize=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PageRevision',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1)])),
|
||||
('status', models.CharField(choices=[('draft', 'Draft'), ('published', 'Published')], default='draft', max_length=10)),
|
||||
('title', models.CharField(max_length=180)),
|
||||
('intro', models.CharField(blank=True, max_length=600)),
|
||||
('seo_title', models.CharField(max_length=120)),
|
||||
('seo_description', models.CharField(max_length=300)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('published_at', models.DateTimeField(blank=True, null=True)),
|
||||
('source_seed_key', models.CharField(blank=True, max_length=120)),
|
||||
('source_seed_version', models.CharField(blank=True, max_length=40)),
|
||||
('content_checksum', models.CharField(blank=True, max_length=64)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='content_page_drafts', to=settings.AUTH_USER_MODEL)),
|
||||
('page', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='revisions', to='content.editorialpage')),
|
||||
('published_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='content_page_publications', to=settings.AUTH_USER_MODEL)),
|
||||
('seo_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='page_og_images', to='content.mediaasset')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='editorialpage',
|
||||
name='published_revision',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='published_for', to='content.pagerevision'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PageSection',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.CharField(max_length=30)),
|
||||
('section_type', models.CharField(max_length=30)),
|
||||
('position', models.PositiveSmallIntegerField()),
|
||||
('visible', models.BooleanField(default=True)),
|
||||
('heading', models.CharField(max_length=120)),
|
||||
('body', models.TextField(blank=True)),
|
||||
('intro', models.CharField(blank=True, max_length=300)),
|
||||
('all_link_label', models.CharField(blank=True, max_length=40)),
|
||||
('primary_action', models.JSONField(blank=True, null=True)),
|
||||
('secondary_action', models.JSONField(blank=True, null=True)),
|
||||
('entries', models.JSONField(blank=True, default=list)),
|
||||
('image_alt', models.CharField(blank=True, max_length=180)),
|
||||
('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sections', to='content.mediaasset')),
|
||||
('revision', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sections', to='content.pagerevision')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['position'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PublicationAudit',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('from_revision', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('to_revision', models.PositiveIntegerField()),
|
||||
('operation', models.CharField(choices=[('create_draft', 'Create draft'), ('update_draft', 'Update draft'), ('publish', 'Publish'), ('restore', 'Restore')], max_length=20)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('actor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
('page', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='content.editorialpage')),
|
||||
('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='content.siteidentity')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SiteRevision',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1)])),
|
||||
('status', models.CharField(choices=[('draft', 'Draft'), ('published', 'Published')], default='draft', max_length=10)),
|
||||
('official_name', models.CharField(max_length=180)),
|
||||
('short_name', models.CharField(max_length=80)),
|
||||
('faculty_subline', models.CharField(blank=True, max_length=140)),
|
||||
('description', models.CharField(blank=True, max_length=500)),
|
||||
('logo_alt', models.CharField(blank=True, max_length=180)),
|
||||
('navigation', models.JSONField(blank=True, default=list, validators=[apps.content.validators.navigation])),
|
||||
('contacts', models.JSONField(blank=True, default=list, validators=[apps.content.validators.contacts])),
|
||||
('footer_copy', models.CharField(blank=True, max_length=300)),
|
||||
('seo_title', models.CharField(blank=True, max_length=120)),
|
||||
('seo_description', models.CharField(blank=True, max_length=300)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('published_at', models.DateTimeField(blank=True, null=True)),
|
||||
('source_seed_key', models.CharField(blank=True, max_length=120)),
|
||||
('source_seed_version', models.CharField(blank=True, max_length=40)),
|
||||
('content_checksum', models.CharField(blank=True, max_length=64)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='content_site_drafts', to=settings.AUTH_USER_MODEL)),
|
||||
('logo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='site_logos', to='content.mediaasset')),
|
||||
('published_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='content_site_publications', to=settings.AUTH_USER_MODEL)),
|
||||
('seo_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='site_og_images', to='content.mediaasset')),
|
||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='revisions', to='content.siteidentity')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='siteidentity',
|
||||
name='published_revision',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='published_for', to='content.siterevision'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='pagerevision',
|
||||
constraint=models.UniqueConstraint(fields=('page', 'number'), name='content_page_revision_number'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='pagesection',
|
||||
constraint=models.UniqueConstraint(fields=('revision', 'key'), name='content_section_key'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='pagesection',
|
||||
constraint=models.UniqueConstraint(fields=('revision', 'position'), name='content_section_position'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='publicationaudit',
|
||||
constraint=models.CheckConstraint(condition=models.Q(models.Q(('page__isnull', True), ('site__isnull', False)), models.Q(('page__isnull', False), ('site__isnull', True)), _connector='OR'), name='content_audit_one_target'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='siterevision',
|
||||
constraint=models.UniqueConstraint(fields=('site', 'number'), name='content_site_revision_number'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='siteidentity',
|
||||
constraint=models.CheckConstraint(condition=models.Q(('id', 1)), name='content_single_site'),
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user