aifeilong 38ec52abf5 Add STAR International API apps and wire production Postgres defaults.
Introduce content/cms/accounts modules with DRF routes, and point default DB settings at the official starintldb instance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 17:08:01 +08:00

436 lines
28 KiB
Python

# Generated by Django 5.2.8 on 2026-10-13 11:36
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Article',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_number', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('title', models.CharField(max_length=500, verbose_name='标题')),
('year', models.IntegerField(blank=True, null=True, verbose_name='年份')),
('score', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='STAR 得分')),
('url', models.URLField(blank=True, default='', verbose_name='原文地址')),
('flags', models.JSONField(blank=True, default=list, verbose_name='标签')),
('content', models.TextField(blank=True, default='', verbose_name='正文')),
('introduction', models.TextField(blank=True, default='', verbose_name='简介')),
('push_date', models.CharField(blank=True, default='', max_length=32, verbose_name='发布日期')),
('read_num', models.PositiveIntegerField(default=0, verbose_name='阅读数')),
('collect_num', models.PositiveIntegerField(default=0, verbose_name='收藏数')),
('like_num', models.PositiveIntegerField(default=0, verbose_name='点赞数')),
('share_num', models.PositiveIntegerField(default=0, verbose_name='分享数')),
('rank', models.IntegerField(blank=True, null=True, verbose_name='首页排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': '文献',
'verbose_name_plural': '文献',
'ordering': ['-year', '-score', 'id'],
},
),
migrations.CreateModel(
name='ArticleType',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('code', models.CharField(help_text='用于文献编号前缀,如 G、C', max_length=8, unique=True, verbose_name='字母标识')),
('note', models.TextField(blank=True, default='', verbose_name='备注')),
],
options={
'verbose_name': '文献类型',
'verbose_name_plural': '文献类型',
'ordering': ['sort', 'id'],
},
),
migrations.CreateModel(
name='Magazine',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('logo', models.URLField(blank=True, default='', verbose_name='Logo')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': '杂志',
'verbose_name_plural': '杂志',
'ordering': ['id'],
},
),
migrations.CreateModel(
name='Organize',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('logo', models.URLField(blank=True, default='', verbose_name='Logo')),
('description', models.TextField(blank=True, default='', verbose_name='描述')),
('url', models.URLField(blank=True, default='', verbose_name='官网')),
('flags', models.JSONField(blank=True, default=list, verbose_name='标签')),
('collect_num', models.PositiveIntegerField(default=0, verbose_name='收藏数')),
('like_num', models.PositiveIntegerField(default=0, verbose_name='点赞数')),
('share_num', models.PositiveIntegerField(default=0, verbose_name='分享数')),
('rank', models.IntegerField(blank=True, null=True, verbose_name='首页排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': '机构',
'verbose_name_plural': '机构',
'ordering': ['rank', 'id'],
},
),
migrations.CreateModel(
name='Professor',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('type', models.IntegerField(blank=True, null=True, verbose_name='分类')),
('role', models.CharField(blank=True, default='', max_length=200, verbose_name='身份')),
('job', models.CharField(blank=True, default='', max_length=200, verbose_name='职称')),
('description', models.TextField(blank=True, default='', verbose_name='简介')),
('email', models.EmailField(blank=True, default='', max_length=254, verbose_name='邮箱')),
('addr', models.CharField(blank=True, default='', max_length=500, verbose_name='地址')),
('logo', models.URLField(blank=True, default='', verbose_name='头像')),
('phone', models.CharField(blank=True, default='', max_length=50, verbose_name='电话')),
('position', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': '专家',
'verbose_name_plural': '专家',
'ordering': ['position', 'id'],
},
),
migrations.CreateModel(
name='Specialty',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('type', models.IntegerField(blank=True, null=True, verbose_name='类型')),
('description', models.TextField(blank=True, default='', verbose_name='描述')),
('logo', models.URLField(blank=True, default='', verbose_name='Logo')),
('content', models.JSONField(blank=True, default=list, verbose_name='内容块')),
('position', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': '专科',
'verbose_name_plural': '专科',
'ordering': ['position', 'id'],
},
),
migrations.CreateModel(
name='StarRule',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('year', models.IntegerField(verbose_name='年份')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
],
options={
'verbose_name': 'STAR 规则',
'verbose_name_plural': 'STAR 规则',
'ordering': ['-year', 'id'],
},
),
migrations.CreateModel(
name='ArticleComment',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('star', models.DecimalField(decimal_places=1, max_digits=3, verbose_name='评价星级')),
('content', models.TextField(blank=True, default='', verbose_name='评价内容')),
('review_status', models.IntegerField(choices=[(1, '待审核'), (2, '不通过'), (3, '通过')], default=1, verbose_name='审核状态')),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='content.article', verbose_name='文献')),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='accounts.member', verbose_name='会员')),
],
options={
'verbose_name': '文献评价',
'verbose_name_plural': '文献评价',
'ordering': ['-id'],
},
),
migrations.AddField(
model_name='article',
name='type',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='articles', to='content.articletype', verbose_name='类型'),
),
migrations.CreateModel(
name='Column',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('uuid', models.CharField(blank=True, default='', max_length=64, verbose_name='栏目 UUID')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('description', models.TextField(blank=True, default='', verbose_name='描述')),
('note', models.TextField(blank=True, default='', verbose_name='备注')),
('template_id', models.IntegerField(blank=True, null=True, verbose_name='页面模板')),
('position', models.IntegerField(choices=[(1, '顶部'), (2, '中部'), (3, '底部')], default=1, verbose_name='位置')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('path', models.CharField(blank=True, default='', max_length=200, verbose_name='前端路径')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.column', verbose_name='父栏目')),
],
options={
'verbose_name': '栏目',
'verbose_name_plural': '栏目',
'ordering': ['sort', 'id'],
},
),
migrations.AddField(
model_name='article',
name='magazines',
field=models.ManyToManyField(blank=True, related_name='articles', to='content.magazine', verbose_name='杂志'),
),
migrations.CreateModel(
name='MagazineCategory',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.magazinecategory', verbose_name='父类别')),
],
options={
'verbose_name': '杂志类别',
'verbose_name_plural': '杂志类别',
'ordering': ['sort', 'id'],
},
),
migrations.AddField(
model_name='magazine',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='magazines', to='content.magazinecategory', verbose_name='杂志类别'),
),
migrations.AddField(
model_name='article',
name='organizes',
field=models.ManyToManyField(blank=True, related_name='articles', to='content.organize', verbose_name='机构'),
),
migrations.CreateModel(
name='OrganizeCategory',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.organizecategory', verbose_name='父类别')),
],
options={
'verbose_name': '机构类别',
'verbose_name_plural': '机构类别',
'ordering': ['sort', 'id'],
},
),
migrations.AddField(
model_name='organize',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='organizes', to='content.organizecategory', verbose_name='机构类别'),
),
migrations.CreateModel(
name='RuleBand',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('star_low', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='最低分')),
('star_high', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='最高分')),
('star', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='星级')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bands', to='content.starrule', verbose_name='规则')),
],
options={
'verbose_name': '评分分档',
'verbose_name_plural': '评分分档',
'ordering': ['star_low', 'id'],
},
),
migrations.CreateModel(
name='Subject',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('serial_num', models.CharField(blank=True, default='', max_length=64, verbose_name='编号')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.subject', verbose_name='父学科')),
],
options={
'verbose_name': '学科',
'verbose_name_plural': '学科',
'ordering': ['sort', 'id'],
},
),
migrations.AddField(
model_name='magazine',
name='subjects',
field=models.ManyToManyField(blank=True, related_name='magazines', to='content.subject', verbose_name='学科'),
),
migrations.AddField(
model_name='article',
name='subjects',
field=models.ManyToManyField(blank=True, related_name='articles', to='content.subject', verbose_name='学科'),
),
migrations.CreateModel(
name='WorkGroup',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('name', models.CharField(max_length=200, verbose_name='名称')),
('description', models.TextField(blank=True, default='', verbose_name='描述')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.workgroup', verbose_name='上级工作组')),
],
options={
'verbose_name': '工作组',
'verbose_name_plural': '工作组',
'ordering': ['sort', 'id'],
},
),
migrations.CreateModel(
name='WorkGroupTerm',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_deleted', models.BooleanField(db_index=True, default=False, verbose_name='已删除')),
('name', models.CharField(max_length=200, verbose_name='届次名称')),
('start_year', models.IntegerField(blank=True, null=True, verbose_name='起始年')),
('end_year', models.IntegerField(blank=True, null=True, verbose_name='结束年')),
('is_current', models.BooleanField(default=False, verbose_name='现任届')),
('sort', models.IntegerField(default=0, verbose_name='排序')),
('is_disabled', models.BooleanField(default=False, verbose_name='禁用')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='content.workgroupterm', verbose_name='同届上级')),
('workgroup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terms', to='content.workgroup', verbose_name='工作组')),
],
options={
'verbose_name': '工作组届次',
'verbose_name_plural': '工作组届次',
'ordering': ['-is_current', '-start_year', 'sort', 'id'],
},
),
migrations.CreateModel(
name='WorkGroupMembership',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('role', models.CharField(blank=True, default='', max_length=200, verbose_name='组内职务')),
('professor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberships', to='content.professor', verbose_name='专家')),
('term', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberships', to='content.workgroupterm', verbose_name='届次')),
],
options={
'verbose_name': '工作组任职',
'verbose_name_plural': '工作组任职',
'unique_together': {('professor', 'term')},
},
),
migrations.AddField(
model_name='professor',
name='terms',
field=models.ManyToManyField(blank=True, related_name='professors', through='content.WorkGroupMembership', to='content.workgroupterm', verbose_name='所属届次'),
),
migrations.CreateModel(
name='ArticleCollect',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='collections', to='content.article', verbose_name='文献')),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='article_collections', to='accounts.member', verbose_name='会员')),
],
options={
'verbose_name': '文献收藏',
'verbose_name_plural': '文献收藏',
'ordering': ['-id'],
'constraints': [models.UniqueConstraint(fields=('article', 'member'), name='content_articlecollect_article_member_uniq')],
},
),
migrations.CreateModel(
name='ArticleLike',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='likes', to='content.article', verbose_name='文献')),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='article_likes', to='accounts.member', verbose_name='会员')),
],
options={
'verbose_name': '文献点赞',
'verbose_name_plural': '文献点赞',
'ordering': ['-id'],
'constraints': [models.UniqueConstraint(fields=('article', 'member'), name='content_articlelike_article_member_uniq')],
},
),
migrations.CreateModel(
name='ArticleShare',
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='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('visitor_key', models.CharField(blank=True, default='', max_length=64, verbose_name='访客标识')),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shares', to='content.article', verbose_name='文献')),
('member', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='article_shares', to='accounts.member', verbose_name='会员')),
],
options={
'verbose_name': '文献分享',
'verbose_name_plural': '文献分享',
'ordering': ['-id'],
'constraints': [models.UniqueConstraint(condition=models.Q(('member__isnull', False)), fields=('article', 'member'), name='content_articleshare_article_member_uniq'), models.UniqueConstraint(condition=models.Q(('visitor_key', ''), _negated=True), fields=('article', 'visitor_key'), name='content_articleshare_article_visitor_uniq')],
},
),
]