# Generated by Django 4.2.30 on 2026-09-15 11:45 from django.conf import settings from django.db import migrations, models import django.db.models.deletion import django.utils.timezone class Migration(migrations.Migration): initial = True dependencies = [ ('profiles', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Post', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=255, verbose_name='Post Title')), ('slug', models.SlugField(allow_unicode=True, blank=True, max_length=255, null=True, unique=True, verbose_name='Slug / URL Identifier')), ('post_type', models.CharField(choices=[('news', 'News & Announcements'), ('article', 'Analytical Article'), ('report', 'Field & Diplomatic Report'), ('interview', 'Expert Interview')], default='article', max_length=50, verbose_name='Post Type')), ('language', models.CharField(choices=[('fa', 'Persian'), ('ar', 'Arabic'), ('en', 'English'), ('ur', 'Urdu'), ('fr', 'French')], default='en', max_length=10, verbose_name='Language')), ('status', models.CharField(choices=[('draft', 'Draft'), ('review', 'Under Review'), ('published', 'Published'), ('archived', 'Archived')], default='published', max_length=20, verbose_name='Publication Status')), ('author_role_label', models.CharField(blank=True, help_text='e.g. Senior Researcher, Center Director, Diplomatic Envoy', max_length=150, null=True, verbose_name='Author Role Label')), ('author_custom_avatar', models.ImageField(blank=True, null=True, upload_to='cms/avatars/%Y/%m/', verbose_name='Custom Author Avatar')), ('featured_image', models.ImageField(blank=True, null=True, upload_to='cms/featured/%Y/%m/', verbose_name='Featured Cover Image')), ('excerpt', models.TextField(blank=True, help_text='Brief summary for search results and cards.', null=True, verbose_name='Excerpt / Summary')), ('content', models.TextField(verbose_name='Rich Text / Markdown Content')), ('tags', models.JSONField(blank=True, default=list, verbose_name='Tags')), ('reading_time_minutes', models.PositiveIntegerField(default=3, verbose_name='Reading Time (Minutes)')), ('views_count', models.PositiveIntegerField(default=0, verbose_name='Views Count')), ('likes_count', models.PositiveIntegerField(default=0, verbose_name='Likes Count')), ('is_featured', models.BooleanField(default=False, verbose_name='Is Featured')), ('publish_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Publish Date')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cms_posts', to=settings.AUTH_USER_MODEL, verbose_name='Author')), ], options={ 'verbose_name': 'Post', 'verbose_name_plural': 'Posts', 'ordering': ('-is_featured', '-publish_date'), }, ), migrations.CreateModel( name='PostCategory', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, verbose_name='Category Name')), ('slug', models.SlugField(allow_unicode=True, max_length=255, unique=True, verbose_name='Slug / URL Identifier')), ('language', models.CharField(choices=[('fa', 'Persian'), ('en', 'English'), ('ar', 'Arabic'), ('ur', 'Urdu'), ('ru', 'Russian')], default='en', max_length=10, verbose_name='Language')), ('description', models.TextField(blank=True, null=True, verbose_name='Category Description')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ], options={ 'verbose_name': 'Post Category', 'verbose_name_plural': 'Post Categories', 'ordering': ('name',), }, ), migrations.CreateModel( name='PostTag', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=100, unique=True, verbose_name='Tag Name')), ('slug', models.SlugField(allow_unicode=True, max_length=100, unique=True, verbose_name='Slug')), ], options={ 'verbose_name': 'Post Tag', 'verbose_name_plural': 'Post Tags', 'ordering': ('name',), }, ), migrations.CreateModel( name='PostComment', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('author_name', models.CharField(blank=True, max_length=255, null=True, verbose_name='Author Name')), ('author_email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Author Email')), ('content', models.TextField(verbose_name='Comment Content')), ('status', models.CharField(choices=[('pending', 'Pending Moderation'), ('approved', 'Approved'), ('spam', 'Spam / Rejected')], default='approved', max_length=20, verbose_name='Moderation Status')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='cms.post', verbose_name='Post')), ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='post_comments', to=settings.AUTH_USER_MODEL, verbose_name='User')), ], options={ 'verbose_name': 'Post Comment', 'verbose_name_plural': 'Post Comments', 'ordering': ('-created_at',), }, ), migrations.AddField( model_name='post', name='category', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='posts', to='cms.postcategory', verbose_name='Category'), ), migrations.AddField( model_name='post', name='institution', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cms_posts', to='profiles.institution', verbose_name='Associated Institution'), ), migrations.CreateModel( name='MediaAsset', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('file', models.FileField(upload_to='cms/media/%Y/%m/', verbose_name='Media File')), ('title', models.CharField(blank=True, max_length=255, null=True, verbose_name='Title / Description')), ('media_type', models.CharField(choices=[('image', 'Image'), ('video', 'Video'), ('audio', 'Audio'), ('document', 'Document / PDF')], default='image', max_length=20, verbose_name='Media Type')), ('file_size', models.PositiveIntegerField(default=0, verbose_name='File Size (Bytes)')), ('dimensions', models.CharField(blank=True, max_length=50, null=True, verbose_name='Dimensions (WxH)')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_cms_media', to=settings.AUTH_USER_MODEL, verbose_name='Uploaded By')), ], options={ 'verbose_name': 'Media Asset', 'verbose_name_plural': 'Media Asset Library', 'ordering': ('-created_at',), }, ), migrations.CreateModel( name='PostLike', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='likes', to='cms.post', verbose_name='Post')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cms_post_likes', to=settings.AUTH_USER_MODEL, verbose_name='User')), ], options={ 'verbose_name': 'Post Like', 'verbose_name_plural': 'Post Likes', 'ordering': ('-created_at',), 'unique_together': {('post', 'user')}, }, ), ]