sync from local backup

This commit is contained in:
chunyu
2026-08-05 23:59:15 +08:00
commit d48ec1747c
358 changed files with 34384 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from learn.models import Course, Chapter
User = get_user_model()
class Command(BaseCommand):
help = '初始化编程学习课程数据'
def handle(self, *args, **options):
admin = User.objects.filter(is_superuser=True).first()
if not admin:
admin = User.objects.first()
if not admin:
self.stdout.write(self.style.ERROR('未找到任何用户,请先创建用户'))
return
# 保留的课程标题(覆盖所有难度和分类)
keep_titles = [
'Python 零基础入门',
'前端入门(HTML + CSS + JS)',
'Java 后端开发进阶',
'Vue 3 企业级实战',
]
# 删除不在保留列表中的课程
deleted_count = Course.objects.exclude(title__in=keep_titles).count()
Course.objects.exclude(title__in=keep_titles).delete()
self.stdout.write(f'已清理 {deleted_count} 个旧课程')
courses_data = [
{
'title': 'Python 零基础入门',
'description': '从零开始学习 Python 编程,掌握基础语法、数据类型、函数和面向对象编程',
'category': 'backend',
'level': 'beginner',
'color': '#667eea',
'icon_name': 'PythonOutlined',
'is_hot': True,
'is_new': True,
'sort_order': 100,
'chapters': [
{'title': 'Python 简介与环境搭建', 'sort_order': 1, 'duration': '30分钟', 'is_free': True},
{'title': '变量与数据类型', 'sort_order': 2, 'duration': '45分钟', 'is_free': True},
{'title': '条件判断与循环', 'sort_order': 3, 'duration': '60分钟', 'is_free': True},
{'title': '函数与模块', 'sort_order': 4, 'duration': '50分钟', 'is_free': True},
{'title': '列表与字典', 'sort_order': 5, 'duration': '55分钟', 'is_free': True},
{'title': '面向对象编程', 'sort_order': 6, 'duration': '70分钟', 'is_free': True},
{'title': '文件操作与异常处理', 'sort_order': 7, 'duration': '45分钟', 'is_free': True},
{'title': '常用标准库', 'sort_order': 8, 'duration': '50分钟', 'is_free': True},
{'title': '项目实战:爬虫入门', 'sort_order': 9, 'duration': '90分钟', 'is_free': True},
]
},
{
'title': '前端入门(HTML + CSS + JS)',
'description': '系统学习网页开发三大基础技术:HTML 结构、CSS 样式和 JavaScript 交互',
'category': 'frontend',
'level': 'beginner',
'color': '#4facfe',
'icon_name': 'Html5Outlined',
'is_hot': True,
'is_new': True,
'sort_order': 90,
'chapters': [
{'title': 'HTML 基础结构', 'sort_order': 1, 'duration': '30分钟', 'is_free': True},
{'title': 'HTML 表单与多媒体', 'sort_order': 2, 'duration': '40分钟', 'is_free': True},
{'title': 'CSS 选择器与样式', 'sort_order': 3, 'duration': '50分钟', 'is_free': True},
{'title': 'CSS 布局与响应式', 'sort_order': 4, 'duration': '60分钟', 'is_free': True},
{'title': 'JavaScript 基础语法', 'sort_order': 5, 'duration': '55分钟', 'is_free': True},
{'title': 'DOM 操作与事件', 'sort_order': 6, 'duration': '45分钟', 'is_free': True},
]
},
{
'title': 'Java 后端开发进阶',
'description': '深入学习 Java 后端开发,掌握 Spring Boot、MySQL 和 RESTful API 设计',
'category': 'backend',
'level': 'advanced',
'color': '#f093fb',
'icon_name': 'ApiOutlined',
'is_hot': True,
'is_new': False,
'sort_order': 80,
'chapters': [
{'title': 'Java 基础回顾', 'sort_order': 1, 'duration': '40分钟', 'is_free': True},
{'title': 'Spring Boot 入门', 'sort_order': 2, 'duration': '60分钟', 'is_free': True},
{'title': 'MySQL 数据库设计', 'sort_order': 3, 'duration': '50分钟', 'is_free': True},
{'title': 'RESTful API 开发', 'sort_order': 4, 'duration': '70分钟', 'is_free': True},
{'title': 'JWT 认证与授权', 'sort_order': 5, 'duration': '45分钟', 'is_free': True},
]
},
{
'title': 'Vue 3 企业级实战',
'description': '使用 Vue 3 + TypeScript + Pinia 开发企业级单页应用',
'category': 'frontend',
'level': 'advanced',
'color': '#43e97b',
'icon_name': 'CodeOutlined',
'is_hot': False,
'is_new': True,
'sort_order': 70,
'chapters': [
{'title': 'Vue 3 组合式 API', 'sort_order': 1, 'duration': '45分钟', 'is_free': True},
{'title': 'TypeScript 基础', 'sort_order': 2, 'duration': '50分钟', 'is_free': True},
{'title': 'Pinia 状态管理', 'sort_order': 3, 'duration': '55分钟', 'is_free': True},
{'title': 'Vue Router 路由', 'sort_order': 4, 'duration': '40分钟', 'is_free': True},
{'title': '项目实战:后台管理系统', 'sort_order': 5, 'duration': '90分钟', 'is_free': True},
]
},
]
created_count = 0
chapter_count = 0
for course_data in courses_data:
chapters_data = course_data.pop('chapters', [])
course_data['author'] = admin
course_data['status'] = 'published'
course, created = Course.objects.update_or_create(
title=course_data['title'],
defaults=course_data
)
if created:
created_count += 1
for chapter_data in chapters_data:
chapter, ch_created = Chapter.objects.update_or_create(
course=course,
title=chapter_data['title'],
defaults=chapter_data
)
if ch_created:
chapter_count += 1
self.stdout.write(
self.style.SUCCESS(
f'成功创建 {created_count} 个课程,共 {chapter_count} 个章节'
)
)