diff --git a/apps/account/migrations/0001_initial.py b/apps/account/migrations/0001_initial.py index bb4bee5..2ab411b 100644 --- a/apps/account/migrations/0001_initial.py +++ b/apps/account/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.18 on 2023-04-01 16:19 +# Generated by Django 3.2.18 on 2023-04-02 16:23 from django.db import migrations, models import django.db.models.deletion @@ -19,32 +19,19 @@ class Migration(migrations.Migration): ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), - ('name', models.CharField(max_length=50, unique=True)), - ('real_name', models.CharField(max_length=50, null=True)), - ('password', models.CharField(max_length=50)), - ('email', models.CharField(max_length=100, null=True, unique=True)), + ('name', models.CharField(max_length=20, unique=True)), + ('real_name', models.CharField(max_length=10, null=True)), + ('phone', models.CharField(max_length=11, null=True, unique=True)), + ('password', models.CharField(max_length=20)), + ('email', models.CharField(max_length=30, null=True, unique=True)), ('gender', models.IntegerField(choices=[(0, 'Unknown'), (1, 'Female'), (2, 'Male')], default=0)), - ('avatar_url', models.CharField(max_length=255)), - ('signature', models.CharField(default=None, max_length=255, null=True)), - ('title_name', models.CharField(max_length=50, null=True)), + ('avatar_url', models.CharField(max_length=255, null=True)), + ('signature', models.CharField(max_length=255, null=True)), + ('title_name', models.CharField(max_length=20, null=True)), ('is_active', models.BooleanField(default=True)), ], options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='Auth', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), - ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), - ('type', models.CharField(choices=[('admin', 'Admin'), ('super admin', 'Superadmin'), ('common', 'Common'), ('contest', 'Contest')], default='common', max_length=50)), - ('permission', models.CharField(max_length=50)), - ('is_active', models.BooleanField(default=True)), - ], - options={ - 'abstract': False, + 'db_table': 'account_account', }, ), migrations.CreateModel( @@ -53,31 +40,28 @@ class Migration(migrations.Migration): ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), - ('role', models.CharField(choices=[('admin', 'Admin'), ('teacher', 'Teacher'), ('tourist', 'Tourist'), ('user', 'User')], default='user', max_length=50)), - ('description', models.CharField(max_length=50, null=True)), + ('role', models.CharField(choices=[('admin', 'Admin'), ('teacher', 'Teacher'), ('tourist', 'Tourist'), ('user', 'User')], default='user', max_length=20)), + ('description', models.CharField(max_length=255, null=True)), ('is_active', models.BooleanField(default=True)), ('accounts', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.account')), ], options={ - 'abstract': False, + 'db_table': 'account_role', }, ), migrations.CreateModel( - name='RoleAuthLink', + name='Auth', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), - ('auth_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.auth')), - ('role_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.role')), + ('type', models.CharField(choices=[('admin', 'Admin'), ('super admin', 'Superadmin'), ('common', 'Common'), ('contest', 'Contest')], default='common', max_length=20)), + ('permission', models.CharField(max_length=50)), + ('is_active', models.BooleanField(default=True)), + ('roles', models.ManyToManyField(to='account.Role')), ], options={ - 'abstract': False, + 'db_table': 'account_auth', }, ), - migrations.AddField( - model_name='auth', - name='roles', - field=models.ManyToManyField(through='account.RoleAuthLink', to='account.Role'), - ), ] diff --git a/apps/account/models.py b/apps/account/models.py index cf845c8..f82f2fa 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -35,40 +35,50 @@ class Gender(models.IntegerChoices): class Account(BaseModel): - name = models.CharField(max_length=50, unique=True) - real_name = models.CharField(max_length=50, null=True) - phone = models.CharField(max_length=11,null=True) - password = models.CharField(max_length=50) - email = models.CharField(max_length=100, unique=True, null=True) + name = models.CharField(max_length=20, unique=True) + real_name = models.CharField(max_length=10, null=True) + phone = models.CharField(max_length=11, null=True,unique=True) + password = models.CharField(max_length=20) + email = models.CharField(max_length=30, unique=True, null=True) gender = models.IntegerField(choices=Gender.choices, default=Gender.UNKNOW) - avatar_url = models.CharField(max_length=255,null=True) - signature = models.CharField(max_length=255, null=True ) - title_name = models.CharField(max_length=50, null=True) + avatar_url = models.CharField(max_length=255, null=True) + signature = models.CharField(max_length=255, null=True) + title_name = models.CharField(max_length=20, null=True) is_active = models.BooleanField(default=True) # 一个账户有一个角色,one to many # role_id = models.ForeignKey("Role", related_name="accounts", on_delete=models.CASCADE) - def verify_password(self, password: str) -> bool: return self.password == password + class Meta: + db_table = "account_account" + class Role(BaseModel): - role = models.CharField(choices=RoleType.choices, max_length=50, default=RoleType.USER) - description = models.CharField(max_length=50, null=True) + role = models.CharField(choices=RoleType.choices, max_length=20, default=RoleType.USER) + description = models.CharField(max_length=255, null=True) is_active = models.BooleanField(default=True) # 一个角色有多个用户 accounts = models.ForeignKey(Account, on_delete=models.CASCADE) + # 一个角色有多个权限,一个权限有多个角色 # auths = models.ManyToManyField("Auth", related_name="roles") + class Meta: + db_table = "account_role" + class Auth(BaseModel): - type = models.CharField(choices=AuthType.choices, max_length=50, default=AuthType.COMMON) + type = models.CharField(choices=AuthType.choices, max_length=20, default=AuthType.COMMON) permission = models.CharField(max_length=50) is_active = models.BooleanField(default=True) - # 一个角色有多个权限,一个权限有多个角色 - roles = models.ManyToManyField(Role, through="RoleAuthLink") + # 角色权限,多对多 + # roles = models.ManyToManyField(Role, through="RoleAuthLink") + roles = models.ManyToManyField(Role) + + class Meta: + db_table = "account_auth" # @@ -79,8 +89,11 @@ class Auth(BaseModel): # Role, on_delete=models.CASCADE) -class RoleAuthLink(BaseModel): - auth_id = models.ForeignKey( - Auth, on_delete=models.CASCADE) - role_id = models.ForeignKey( - Role, on_delete=models.CASCADE) +# class RoleAuthLink(BaseModel): +# auth_id = models.ForeignKey( +# Auth, on_delete=models.CASCADE) +# role_id = models.ForeignKey( +# Role, on_delete=models.CASCADE) +# +# class Meta: +# db_table = "role_link_auth" diff --git a/apps/course/migrations/0001_initial.py b/apps/course/migrations/0001_initial.py new file mode 100644 index 0000000..a5f02ab --- /dev/null +++ b/apps/course/migrations/0001_initial.py @@ -0,0 +1,173 @@ +# Generated by Django 3.2.18 on 2023-04-02 16:23 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Chapter', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('index', models.CharField(choices=[('第一章', 'One'), ('第二章', 'Two'), ('第三章', 'Three'), ('第四章', 'Four'), ('第五章', 'Five'), ('第六章', 'Six'), ('第七章', 'Seven'), ('第八章', 'Eight'), ('第九章', 'Nine'), ('第十章', 'Ten'), ('第十一章', 'Eleven'), ('第十二章', 'Twelve')], max_length=50)), + ('title', models.CharField(max_length=100)), + ('description', models.TextField(null=True)), + ('cover_img_url', models.CharField(default=None, max_length=255)), + ('view_count', models.IntegerField(default=0)), + ('is_active', models.BooleanField(default=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Course', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('title', models.CharField(max_length=50)), + ('description', models.TextField(null=True)), + ('price', models.FloatField(default=0)), + ('cover_img_url', models.CharField(max_length=255)), + ('view_count', models.IntegerField(default=0)), + ('sale_count', models.IntegerField(default=0)), + ('is_active', models.BooleanField(default=True)), + ('level', models.IntegerField(choices=[(0, 'Easy'), (1, 'Base'), (2, 'Advanced'), (3, 'Pro')], default=1)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Language', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('content_type', models.CharField(max_length=50)), + ('description', models.TextField()), + ('name', models.CharField(max_length=50)), + ('compile_command', models.TextField()), + ('is_spj', models.BooleanField()), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Lession', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('index', models.IntegerField()), + ('title', models.CharField(max_length=100)), + ('is_active', models.BooleanField(default=True)), + ('chapter_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.chapter')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Problem', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('judge_type', models.CharField(choices=[('spj', 'Spj'), ('common', 'Common')], default='common', max_length=10)), + ('problem_id', models.CharField(max_length=20, unique=True)), + ('title', models.CharField(max_length=100)), + ('type', models.IntegerField(choices=[(0, 'Acm'), (1, 'Oi')], default=1)), + ('time_limit', models.IntegerField(default=1000)), + ('memory_limit', models.IntegerField(default=128)), + ('start_limit', models.IntegerField(default=128)), + ('description', models.TextField()), + ('input_description', models.TextField()), + ('output_description', models.TextField()), + ('examples', models.TextField()), + ('degree', models.IntegerField(choices=[(0, 'Easy'), (1, 'Base'), (2, 'Medium'), (3, 'Hard')], default=1)), + ('hint', models.TextField(null=True)), + ('auth', models.IntegerField(choices=[(0, 'Public'), (1, 'Private'), (2, 'Contest')], default=0)), + ('io_score', models.IntegerField(default=100)), + ('code_share', models.BooleanField(default=True)), + ('spj_code', models.TextField(null=True)), + ('spj_language', models.CharField(max_length=50, null=True)), + ('is_remove_end_blank', models.BooleanField(default=True)), + ('is_open_case', models.BooleanField(default=True)), + ('is_upload_case', models.BooleanField(default=True)), + ('is_active', models.BooleanField(default=True)), + ('lession_id', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='course.lession')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Video', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('title', models.CharField(max_length=100)), + ('img_url', models.CharField(max_length=255)), + ('video_url', models.CharField(max_length=255)), + ('count', models.IntegerField(default=0)), + ('is_free', models.BooleanField(default=False)), + ('duration', models.IntegerField()), + ('size', models.IntegerField()), + ('status', models.IntegerField(choices=[(0, 'Private'), (1, 'Uploading'), (2, 'Public')], default=2)), + ('description', models.CharField(max_length=255, null=True)), + ('is_active', models.BooleanField(default=True)), + ('lession', models.OneToOneField(on_delete=django.db.models.deletion.DO_NOTHING, to='course.lession')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('name', models.CharField(max_length=50)), + ('status', models.BooleanField(default=True)), + ('problems', models.ManyToManyField(to='course.Problem')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='chapter', + name='course_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.course'), + ), + migrations.CreateModel( + name='Case', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('input', models.TextField()), + ('output', models.TextField()), + ('status', models.BooleanField(default=True)), + ('problem_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.problem')), + ], + options={ + 'db_table': 'case', + }, + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 71a8362..95fc816 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -1,3 +1,167 @@ from django.db import models +from apps.base.models import BaseModel -# Create your models here. + +class ProblemType(models.IntegerChoices): + ACM = 0 + OI = 1 + + +class ProblemAuth(models.IntegerChoices): + PUBLIC = 0 + PRIVATE = 1 + CONTEST = 2 + + +class Degree(models.IntegerChoices): + EASY = 0 + BASE = 1 + MEDIUM = 2 + HARD = 3 + + +class VideoStatus(models.IntegerChoices): + PRIVATE = 0 + UPLOADING = 1 + PUBLIC = 2 + + +class CourseLevel(models.IntegerChoices): + EASY = 0 + BASE = 1 + Advanced = 2 + PRO = 3 + + +class JudgeType(models.TextChoices): + SPJ = "spj" + COMMON = "common" + + +class ChapterIndex(models.TextChoices): + ONE = "第一章" + TWO = "第二章" + THREE = "第三章" + FOUR = "第四章" + FIVE = "第五章" + SIX = "第六章" + SEVEN = "第七章" + EIGHT = "第八章" + NINE = "第九章" + TEN = "第十章" + ELEVEN = "第十一章" + TWELVE = "第十二章" + + +class Course(BaseModel): + """课程模型 + + """ + title = models.CharField(max_length=50) + description = models.TextField(null=True) + price = models.FloatField(default=0) + cover_img_url = models.CharField(max_length=255) + view_count = models.IntegerField(default=0) + sale_count = models.IntegerField(default=0) + is_active = models.BooleanField(default=True) + # 课程分类,默认为基础 + level = models.IntegerField( + choices=CourseLevel.choices, default=CourseLevel.BASE) + + +class Chapter(BaseModel): + """章节模型 + + """ + index = models.CharField(choices=ChapterIndex.choices,max_length=50) + title = models.CharField(max_length=100) + description = models.TextField(null=True) + cover_img_url = models.CharField(max_length=255, default=None) + view_count = models.IntegerField(default=0) + is_active = models.BooleanField(default=True) + + course_id = models.ForeignKey( + Course, on_delete=models.CASCADE) + + +class Lession(BaseModel): + """节模型 + """ + index = models.IntegerField() + title = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) + # 一个章节有多节课,one to many + chapter_id = models.ForeignKey( + Chapter, on_delete=models.CASCADE) + # 一节课一个视频,一个视频多节课,one to many + # 一节课有多个问题,一个问题有多节课 ,many to many + + +class Video(BaseModel): + """视频模型 + """ + title = models.CharField(max_length=100) + img_url = models.CharField(max_length=255) + video_url = models.CharField(max_length=255) + count = models.IntegerField(default=0) + is_free = models.BooleanField(default=False) + duration = models.IntegerField() # s + size = models.IntegerField() # kb + status = models.IntegerField(choices=VideoStatus.choices, default=VideoStatus.PUBLIC) + description = models.CharField(max_length=255, null=True) + is_active = models.BooleanField(default=True) + lession = models.OneToOneField( + Lession, on_delete=models.DO_NOTHING) + + +class Problem(BaseModel): + """问题模型""" + judge_type = models.CharField(choices=JudgeType.choices, max_length=10, default=JudgeType.COMMON) + problem_id = models.CharField(max_length=20, unique=True) + title = models.CharField(max_length=100) + type = models.IntegerField(choices=ProblemType.choices, default=ProblemType.OI) + time_limit = models.IntegerField(default=1000) # 1000ms + memory_limit = models.IntegerField(default=128) # 128mb + start_limit = models.IntegerField(default=128) # 128mb + description = models.TextField() + input_description = models.TextField() + output_description = models.TextField() + examples = models.TextField() + degree = models.IntegerField(choices=Degree.choices, default=Degree.BASE) + hint = models.TextField(null=True) + auth = models.IntegerField(choices=ProblemAuth.choices, default=ProblemAuth.PUBLIC) + io_score = models.IntegerField(default=100) # 满分100 + code_share = models.BooleanField(default=True) + spj_code = models.TextField(null=True) + spj_language = models.CharField(max_length=50, null=True) + is_remove_end_blank = models.BooleanField(default=True) + is_open_case = models.BooleanField(default=True) + is_upload_case = models.BooleanField(default=True) + is_active = models.BooleanField(default=True) + lession_id = models.ForeignKey(Lession, on_delete=models.DO_NOTHING) + + +class Tag(BaseModel): + """标签模型""" + name = models.CharField(max_length=50) + status = models.BooleanField(default=True) + # 问题,标签 多对多 + problems = models.ManyToManyField(Problem) + + +class Case(BaseModel): + input = models.TextField() + output = models.TextField() + status = models.BooleanField(default=True) + problem_id = models.ForeignKey(Problem, on_delete=models.CASCADE) + + class Meta: + db_table = "case" + + +class Language(BaseModel): + content_type = models.CharField(max_length=50) + description = models.TextField() + name = models.CharField(max_length=50) + compile_command = models.TextField() + is_spj = models.BooleanField()