Compare commits

...

No commits in common. 'master' and 'wavesign' have entirely different histories.

275 changed files with 25563 additions and 773 deletions
Split View
  1. +30
    -1
      .gitignore
  2. +0
    -0
      Community/__init__.py
  3. +3
    -0
      Community/admin.py
  4. +6
    -0
      Community/apps.py
  5. +86
    -0
      Community/migrations/0001_initial.py
  6. +67
    -0
      Community/migrations/0002_initial.py
  7. +0
    -0
      Community/migrations/__init__.py
  8. +36
    -0
      Community/models.py
  9. +132
    -0
      Community/tests.py
  10. +15
    -0
      Community/urls.py
  11. +134
    -0
      Community/views.py
  12. +0
    -0
      Home/__init__.py
  13. +3
    -0
      Home/admin.py
  14. +6
    -0
      Home/apps.py
  15. +0
    -0
      Home/migrations/__init__.py
  16. +3
    -0
      Home/models.py
  17. +10
    -0
      Home/tests.py
  18. +6
    -0
      Home/urls.py
  19. +5
    -0
      Home/views.py
  20. +0
    -0
      LifeServing/__init__.py
  21. +3
    -0
      LifeServing/admin.py
  22. +6
    -0
      LifeServing/apps.py
  23. +0
    -0
      LifeServing/migrations/__init__.py
  24. +3
    -0
      LifeServing/models.py
  25. +10
    -0
      LifeServing/tests.py
  26. +6
    -0
      LifeServing/urls.py
  27. +6
    -0
      LifeServing/views.py
  28. +0
    -0
      MyPage/__init__.py
  29. +3
    -0
      MyPage/admin.py
  30. +6
    -0
      MyPage/apps.py
  31. +15
    -0
      MyPage/forms.py
  32. +64
    -0
      MyPage/migrations/0001_initial.py
  33. +45
    -0
      MyPage/migrations/0002_initial.py
  34. +0
    -0
      MyPage/migrations/__init__.py
  35. +32
    -0
      MyPage/models.py
  36. +116
    -0
      MyPage/tests.py
  37. +10
    -0
      MyPage/urls.py
  38. +140
    -0
      MyPage/views.py
  39. +49
    -115
      README.md
  40. +0
    -0
      SLClassroom/__init__.py
  41. +3
    -0
      SLClassroom/admin.py
  42. +6
    -0
      SLClassroom/apps.py
  43. +0
    -0
      SLClassroom/migrations/__init__.py
  44. +3
    -0
      SLClassroom/models.py
  45. +10
    -0
      SLClassroom/tests.py
  46. +6
    -0
      SLClassroom/urls.py
  47. +6
    -0
      SLClassroom/views.py
  48. +0
    -0
      Schedule/__init__.py
  49. +3
    -0
      Schedule/admin.py
  50. +6
    -0
      Schedule/apps.py
  51. +49
    -0
      Schedule/migrations/0001_initial.py
  52. +47
    -0
      Schedule/migrations/0002_initial.py
  53. +0
    -0
      Schedule/migrations/__init__.py
  54. +26
    -0
      Schedule/models.py
  55. +15
    -0
      Schedule/serializers.py
  56. +65
    -0
      Schedule/tests.py
  57. +20
    -0
      Schedule/urls.py
  58. +94
    -0
      Schedule/views.py
  59. +0
    -0
      WaveSign/__init__.py
  60. +16
    -0
      WaveSign/asgi.py
  61. +168
    -0
      WaveSign/settings.py
  62. +22
    -0
      WaveSign/urls.py
  63. +10
    -0
      WaveSign/views.py
  64. +16
    -0
      WaveSign/wsgi.py
  65. +268
    -0
      WaveSign测试文档.md
  66. +103
    -0
      WaveSign需求分析文档.md
  67. BIN
      db.sqlite3
  68. +1
    -0
      htmlcov/.gitignore
  69. +1147
    -0
      htmlcov/class_index.html
  70. +733
    -0
      htmlcov/coverage_html_cb_6fb7b396.js
  71. BIN
      htmlcov/favicon_32_cb_58284776.png
  72. +1595
    -0
      htmlcov/function_index.html
  73. +608
    -0
      htmlcov/index.html
  74. BIN
      htmlcov/keybd_closed_cb_ce680311.png
  75. +119
    -0
      htmlcov/manage_py.html
  76. +1
    -0
      htmlcov/status.json
  77. +337
    -0
      htmlcov/style_cb_8e611ae1.css
  78. +183
    -0
      htmlcov/z_1267b767d4b92e81_0001_initial_py.html
  79. +164
    -0
      htmlcov/z_1267b767d4b92e81_0002_initial_py.html
  80. +97
    -0
      htmlcov/z_1267b767d4b92e81___init___py.html
  81. +97
    -0
      htmlcov/z_12dff67f314accae___init___py.html
  82. +146
    -0
      htmlcov/z_1778eb5d946b9af5_0001_initial_py.html
  83. +144
    -0
      htmlcov/z_1778eb5d946b9af5_0002_initial_py.html
  84. +97
    -0
      htmlcov/z_1778eb5d946b9af5___init___py.html
  85. +97
    -0
      htmlcov/z_3d86ff49411af6eb___init___py.html
  86. +97
    -0
      htmlcov/z_4f885700d30561f0___init___py.html
  87. +100
    -0
      htmlcov/z_4f885700d30561f0_admin_py.html
  88. +103
    -0
      htmlcov/z_4f885700d30561f0_apps_py.html
  89. +100
    -0
      htmlcov/z_4f885700d30561f0_models_py.html
  90. +107
    -0
      htmlcov/z_4f885700d30561f0_tests_py.html
  91. +103
    -0
      htmlcov/z_4f885700d30561f0_urls_py.html
  92. +102
    -0
      htmlcov/z_4f885700d30561f0_views_py.html
  93. +97
    -0
      htmlcov/z_5c71e8f1e4812293___init___py.html
  94. +100
    -0
      htmlcov/z_5c71e8f1e4812293_admin_py.html
  95. +103
    -0
      htmlcov/z_5c71e8f1e4812293_apps_py.html
  96. +123
    -0
      htmlcov/z_5c71e8f1e4812293_models_py.html
  97. +112
    -0
      htmlcov/z_5c71e8f1e4812293_serializers_py.html
  98. +162
    -0
      htmlcov/z_5c71e8f1e4812293_tests_py.html
  99. +117
    -0
      htmlcov/z_5c71e8f1e4812293_urls_py.html
  100. +191
    -0
      htmlcov/z_5c71e8f1e4812293_views_py.html

+ 30
- 1
.gitignore View File

@ -1,3 +1,32 @@
# Python
*.pyc
__pycache__/
*.pyo
*.pyd
*.db
# 虚拟环境
venv/
.venv/
ENV/
env/
# Django
db.sqlite3
media/
*.log
# VS Code
.vscode/
# macOS & Windows 临时文件
.DS_Store
Thumbs.db
build/
node_modules/
model/
dist/
src-tauri/
~$项目测试结果.xlsx
.vite/

+ 0
- 0
Community/__init__.py View File


+ 3
- 0
Community/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
Community/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CommunityConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "Community"

+ 86
- 0
Community/migrations/0001_initial.py View File

@ -0,0 +1,86 @@
# Generated by Django 5.2 on 2025-05-30 01:17
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Comment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("content", models.TextField()),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name="Favorite",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name="Like",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name="Post",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("content", models.TextField(verbose_name="内容")),
(
"image",
models.ImageField(blank=True, null=True, upload_to="post_images/"),
),
(
"video",
models.FileField(blank=True, null=True, upload_to="post_videos/"),
),
("like_count", models.PositiveIntegerField(default=0)),
("comment_count", models.PositiveIntegerField(default=0)),
("favorite_count", models.PositiveIntegerField(default=0)),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
]

+ 67
- 0
Community/migrations/0002_initial.py View File

@ -0,0 +1,67 @@
# Generated by Django 5.2 on 2025-05-30 01:17
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("Community", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name="comment",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="favorite",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="like",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="post",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="like",
name="post",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="Community.post"
),
),
migrations.AddField(
model_name="favorite",
name="post",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="Community.post"
),
),
migrations.AddField(
model_name="comment",
name="post",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="Community.post"
),
),
]

+ 0
- 0
Community/migrations/__init__.py View File


+ 36
- 0
Community/models.py View File

@ -0,0 +1,36 @@
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings # 使用 Django 的配置抽象层
# 帖子模型
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
content = models.TextField(verbose_name="内容")
image = models.ImageField(upload_to='post_images/', blank=True, null=True)
video = models.FileField(upload_to='post_videos/', blank=True, null=True)
like_count = models.PositiveIntegerField(default=0) # 👍 新增点赞字段
comment_count = models.PositiveIntegerField(default=0) # 👍 新增评论字段
favorite_count = models.PositiveIntegerField(default=0) # 👍 新增点赞字段
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username} 的帖子"
# 互动模型(点赞、评论、收藏)
class Like(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Comment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Favorite(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)

+ 132
- 0
Community/tests.py View File

@ -0,0 +1,132 @@
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from .models import Post, Like, Comment, Favorite
import json
User = get_user_model()
class PostModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser', password='testpass')
self.post = Post.objects.create(user=self.user, content='test content')
def test_str(self):
self.assertIn(self.user.username, str(self.post))
def test_post_creation(self):
self.assertEqual(Post.objects.count(), 1)
class LikeModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser2', password='testpass')
self.post = Post.objects.create(user=self.user, content='test content')
self.like = Like.objects.create(user=self.user, post=self.post)
def test_like_creation(self):
self.assertEqual(Like.objects.count(), 1)
class CommentModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser3', password='testpass')
self.post = Post.objects.create(user=self.user, content='test content')
self.comment = Comment.objects.create(user=self.user, post=self.post, content='nice!')
def test_comment_creation(self):
self.assertEqual(Comment.objects.count(), 1)
class FavoriteModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser4', password='testpass')
self.post = Post.objects.create(user=self.user, content='test content')
self.favorite = Favorite.objects.create(user=self.user, post=self.post)
def test_favorite_creation(self):
self.assertEqual(Favorite.objects.count(), 1)
class CommunityViewsTest(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(username='testuser5', password='testpass')
self.post = Post.objects.create(user=self.user, content='test content')
def test_post_list_view(self):
response = self.client.get(reverse('community'))
self.assertEqual(response.status_code, 200)
def test_create_post_view_not_logged_in(self):
response = self.client.get(reverse('create_post'))
self.assertEqual(response.status_code, 302) # redirect to login
def test_like_post_view(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('like_post', args=[self.post.id]))
self.assertEqual(response.status_code, 200)
def test_create_post_with_content(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('create_post'), {'content': 'new post'})
self.assertEqual(response.status_code, 302)
def test_create_post_no_content(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('create_post'), {'content': ''})
self.assertEqual(response.status_code, 302)
def test_like_post_twice(self):
self.client.login(username='testuser5', password='testpass')
self.client.post(reverse('like_post', args=[self.post.id]))
response = self.client.post(reverse('like_post', args=[self.post.id]))
self.assertJSONEqual(response.content, {'success': False, 'message': '已点赞'})
def test_like_post_not_exist(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('like_post', args=[9999]))
self.assertEqual(response.status_code, 404)
data = json.loads(response.content)
self.assertEqual(data['error'], '帖子不存在')
def test_comment_post_empty(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('comment_post', args=[self.post.id]), {'content': ''})
self.assertJSONEqual(response.content, {'success': False, 'message': '评论不能为空'})
def test_comment_post_not_exist(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('comment_post', args=[9999]), {'content': 'hi'})
self.assertEqual(response.status_code, 404)
data = json.loads(response.content)
self.assertEqual(data['error'], '帖子不存在')
def test_favorite_post_twice(self):
self.client.login(username='testuser5', password='testpass')
self.client.post(reverse('favorite_post', args=[self.post.id]))
response = self.client.post(reverse('favorite_post', args=[self.post.id]))
self.assertJSONEqual(response.content, {'success': False, 'message': '已收藏'})
def test_favorite_post_not_exist(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('favorite_post', args=[9999]))
self.assertEqual(response.status_code, 404)
data = json.loads(response.content)
self.assertEqual(data['error'], '帖子不存在')
def test_toggle_follow_self(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('toggle_follow', args=[self.user.id]))
self.assertJSONEqual(response.content, {'success': False, 'message': '不能关注自己'})
def test_toggle_follow_not_exist(self):
self.client.login(username='testuser5', password='testpass')
response = self.client.post(reverse('toggle_follow', args=[9999]))
self.assertJSONEqual(response.content, {'success': False, 'message': '用户不存在'})
def test_toggle_follow_and_unfollow(self):
self.client.login(username='testuser5', password='testpass')
# 新建另一个用户
user2 = User.objects.create_user(username='testuser6', password='testpass')
response = self.client.post(reverse('toggle_follow', args=[user2.id]))
self.assertJSONEqual(response.content, {'success': True, 'following': True, 'message': '关注成功'})
# 再次调用应为取消关注
response = self.client.post(reverse('toggle_follow', args=[user2.id]))
self.assertJSONEqual(response.content, {'success': True, 'following': False, 'message': '已取消关注'})

+ 15
- 0
Community/urls.py View File

@ -0,0 +1,15 @@
from django.urls import re_path as url
from . import views
from django.urls import path
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path ('', views.post_list, name='community'), # 首页就是帖子列表
path('create_post/', views.create_post, name='create_post'), # 专用于发布逻辑
path ('post_list/', views.post_list, name='post_list'), # 浏览已发布帖子
path('like_post/<int:post_id>/', views.like_post, name='like_post'), # 点赞帖子
path('comment_post/<int:post_id>/', views.comment_post, name='comment_post'), # 评论帖子
path('favorite_post/<int:post_id>/', views.favorite_post, name='favorite_post'), # 收藏帖子
path('toggle_follow/<int:user_id>/', views.toggle_follow, name='toggle_follow'), # 关注
]

+ 134
- 0
Community/views.py View File

@ -0,0 +1,134 @@
from django.shortcuts import render, redirect
from .models import Post, Like, Comment, Favorite
from MyPage.models import Follow
from users.models import CustomUser
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
def index(request):
posts = Post.objects.all().order_by('-created_at')
return render(request, 'Community.html', {'posts': posts})
@login_required(login_url='login')
@csrf_exempt
def create_post(request):
if request.method == 'POST':
content = request.POST.get('content', '').strip()
image = request.FILES.get('image')
video = request.FILES.get('video')
if content or image or video:
try:
post = Post.objects.create(
user=request.user,
content=content,
image=image,
video=video
)
print("✅ 帖子成功写入数据库!ID:", post.id)
except Exception as e:
print("❌ 帖子写入失败:", e)
else:
print("⚠️ 无内容、图片或视频,跳过写入。")
return redirect('community')
# GET 请求展示帖子列表
posts = Post.objects.all().order_by('-created_at')
return render(request, 'Community.html', {'posts': posts})
# 浏览已发布帖子
def post_list(request):
posts = Post.objects.all().order_by('-created_at')
return render(request, 'Community.html', {'posts': posts})
@login_required(login_url='login')
@csrf_exempt
def like_post(request, post_id):
user = request.user
try:
post = Post.objects.get(id=post_id)
# 检查是否已点赞
if Like.objects.filter(user=user, post=post).exists():
return JsonResponse({'success': False, 'message': '已点赞'})
# 没有则创建记录
Like.objects.create(user=user, post=post)
post.like_count += 1
post.save()
return JsonResponse({'success': True, 'likes': post.like_count})
except Post.DoesNotExist:
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404)
@login_required(login_url='login')
@csrf_exempt
def comment_post(request, post_id):
if request.method == 'POST':
content = request.POST.get('content', '').strip()
if not content:
return JsonResponse({'success': False, 'message': '评论不能为空'})
try:
post = Post.objects.get(id=post_id)
comment = Comment.objects.create(user=request.user, post=post, content=content)
post.comment_count += 1
post.save()
return JsonResponse({
'success': True,
'username': comment.user.username,
'content': comment.content,
'created_at': comment.created_at.strftime('%Y-%m-%d %H:%M:%S'),
'comment_count': post.comment_count
})
except Post.DoesNotExist:
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404)
@login_required(login_url='login')
@csrf_exempt
def favorite_post(request, post_id):
user = request.user
try:
post = Post.objects.get(id=post_id)
# 检查是否已收藏
if Favorite.objects.filter(user=user, post=post).exists():
return JsonResponse({'success': False, 'message': '已收藏'})
# 没有则创建记录
Favorite.objects.create(user=user, post=post)
post.favorite_count += 1
post.save()
return JsonResponse({'success': True, 'favorites': post.favorite_count})
except Post.DoesNotExist:
return JsonResponse({'success': False, 'error': '帖子不存在'}, status=404)
@login_required(login_url='login')
@csrf_exempt
def toggle_follow(request, user_id):
follower = request.user
try:
followed = CustomUser.objects.get(id=user_id)
if follower == followed:
return JsonResponse({'success': False, 'message': '不能关注自己'})
existing = Follow.objects.filter(follower=follower, followed=followed)
if existing.exists():
existing.delete()
return JsonResponse({'success': True, 'following': False, 'message': '已取消关注'})
else:
Follow.objects.create(follower=follower, followed=followed)
return JsonResponse({'success': True, 'following': True, 'message': '关注成功'})
except CustomUser.DoesNotExist:
return JsonResponse({'success': False, 'message': '用户不存在'})
def post_list(request):
posts = Post.objects.all().order_by('-created_at')
user = request.user
for post in posts:
post.is_followed = False
if user.is_authenticated and post.user != user:
post.is_followed = Follow.objects.filter(follower=user, followed=post.user).exists()
return render(request, 'Community.html', {'posts': posts})

+ 0
- 0
Home/__init__.py View File


+ 3
- 0
Home/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
Home/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class HomeConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "Home"

+ 0
- 0
Home/migrations/__init__.py View File


+ 3
- 0
Home/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 10
- 0
Home/tests.py View File

@ -0,0 +1,10 @@
from django.test import TestCase, Client
from django.urls import reverse
# Create your tests here.
class HomeViewTest(TestCase):
def test_home_page(self):
client = Client()
response = client.get(reverse('home'))
self.assertEqual(response.status_code, 200)

+ 6
- 0
Home/urls.py View File

@ -0,0 +1,6 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='home'),
]

+ 5
- 0
Home/views.py View File

@ -0,0 +1,5 @@
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'home.html')

+ 0
- 0
LifeServing/__init__.py View File


+ 3
- 0
LifeServing/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
LifeServing/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class LifeservingConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "LifeServing"

+ 0
- 0
LifeServing/migrations/__init__.py View File


+ 3
- 0
LifeServing/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 10
- 0
LifeServing/tests.py View File

@ -0,0 +1,10 @@
from django.test import TestCase, Client
from django.urls import reverse
# Create your tests here.
class LifeServingViewTest(TestCase):
def test_life_serving_page(self):
client = Client()
response = client.get(reverse('life_serving'))
self.assertEqual(response.status_code, 200)

+ 6
- 0
LifeServing/urls.py View File

@ -0,0 +1,6 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='life_serving'),
]

+ 6
- 0
LifeServing/views.py View File

@ -0,0 +1,6 @@
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'LifeServing.html')

+ 0
- 0
MyPage/__init__.py View File


+ 3
- 0
MyPage/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
MyPage/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class MypageConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "MyPage"

+ 15
- 0
MyPage/forms.py View File

@ -0,0 +1,15 @@
from django import forms
from users.models import CustomUser
from .models import UserProfile
# 表单上传更新
class ProfileUpdateForm(forms.ModelForm):
username = forms.CharField(max_length=150, required=True)
avatar = forms.ImageField(required=False)
personal_background = forms.ImageField(required=False)
page_background = forms.ImageField(required=False)
bio = forms.CharField(widget=forms.Textarea, required=False)
class Meta:
model = CustomUser
fields = ['username', 'avatar']

+ 64
- 0
MyPage/migrations/0001_initial.py View File

@ -0,0 +1,64 @@
# Generated by Django 5.2 on 2025-05-30 01:17
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Follow",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name="UserProfile",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("bio", models.TextField(blank=True, verbose_name="个人简介")),
(
"personal_background",
models.ImageField(
blank=True,
default="personal_backgrounds/default.png",
null=True,
upload_to="personal_backgrounds/",
verbose_name="个人资料背景",
),
),
(
"page_background",
models.ImageField(
blank=True,
default="page_backgrounds/default.png",
null=True,
upload_to="page_backgrounds/",
verbose_name="页面背景",
),
),
("updated_at", models.DateTimeField(auto_now=True)),
],
),
]

+ 45
- 0
MyPage/migrations/0002_initial.py View File

@ -0,0 +1,45 @@
# Generated by Django 5.2 on 2025-05-30 01:17
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("MyPage", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name="follow",
name="followed",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="followers",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="follow",
name="follower",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="following",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="userprofile",
name="user",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="profile",
to=settings.AUTH_USER_MODEL,
),
),
]

+ 0
- 0
MyPage/migrations/__init__.py View File


+ 32
- 0
MyPage/models.py View File

@ -0,0 +1,32 @@
from django.db import models
from django.conf import settings
from Community.models import Post # 假设帖子模型在 Community 应用中
from django.contrib.auth import get_user_model
User = get_user_model()
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField(blank=True, verbose_name="个人简介")
personal_background = models.ImageField(upload_to='personal_backgrounds/', blank=True, null=True,
verbose_name="个人资料背景", default='personal_backgrounds/default.png')
page_background = models.ImageField(upload_to='page_backgrounds/', blank=True, null=True,
verbose_name="页面背景", default='page_backgrounds/default.png')
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.user.username} 的个人资料"
def get_user_posts(self):
return Post.objects.filter(user=self.user).order_by('-created_at')
class Follow(models.Model):
"""用于记录用户之间的关注关系"""
follower = models.ForeignKey(User, related_name='following', on_delete=models.CASCADE)
followed = models.ForeignKey(User, related_name='followers', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.follower.username} 关注了 {self.following.username}"

+ 116
- 0
MyPage/tests.py View File

@ -0,0 +1,116 @@
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from .models import UserProfile, Follow
from django.core.files.uploadedfile import SimpleUploadedFile
import json
User = get_user_model()
class UserProfileModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser', password='testpass')
self.profile = self.user.profile
def test_str(self):
self.assertIn(self.user.username, str(self.profile))
class FollowModelTest(TestCase):
def setUp(self):
self.user1 = User.objects.create_user(username='user1', password='testpass')
self.user2 = User.objects.create_user(username='user2', password='testpass')
self.follow = Follow.objects.create(follower=self.user1, followed=self.user2)
def test_follow_creation(self):
self.assertEqual(Follow.objects.count(), 1)
class MyPageViewTest(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(username='testuser2', password='testpass')
self.client.login(username='testuser2', password='testpass')
def test_my_page_view(self):
response = self.client.get(reverse('my_page'))
self.assertEqual(response.status_code, 200)
class MyPageViewsTest(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(username='testuser3', password='testpass')
self.client.login(username='testuser3', password='testpass')
def test_my_page_view_logged_in(self):
response = self.client.get(reverse('my_page'))
self.assertEqual(response.status_code, 200)
def test_my_page_view_not_logged_in(self):
self.client.logout()
response = self.client.get(reverse('my_page'))
self.assertEqual(response.status_code, 302)
def test_upload_avatar_success(self):
image = SimpleUploadedFile('avatar.png', b'file_content', content_type='image/png')
response = self.client.post(reverse('upload_avatar'), {'avatar': image})
data = json.loads(response.content)
self.assertTrue(data['success'])
self.assertIn('avatar_url', data)
def test_upload_avatar_no_file(self):
response = self.client.post(reverse('upload_avatar'))
data = json.loads(response.content)
self.assertFalse(data['success'])
self.assertEqual(data['message'], '没有接收到avatar文件')
def test_upload_avatar_not_logged_in(self):
self.client.logout()
response = self.client.post(reverse('upload_avatar'))
data = json.loads(response.content)
self.assertFalse(data['success'])
def test_upload_banner_success(self):
image = SimpleUploadedFile('banner.png', b'file_content', content_type='image/png')
response = self.client.post(reverse('upload_banner'), {'personal_background': image})
data = json.loads(response.content)
self.assertTrue(data['success'])
self.assertIn('bg_url', data)
def test_upload_banner_no_file(self):
response = self.client.post(reverse('upload_banner'))
data = json.loads(response.content)
self.assertFalse(data['success'])
self.assertEqual(data['message'], '未收到文件')
def test_upload_banner_not_logged_in(self):
self.client.logout()
response = self.client.post(reverse('upload_banner'))
data = json.loads(response.content)
self.assertFalse(data['success'])
def test_upload_pagebg_success(self):
image = SimpleUploadedFile('pagebg.png', b'file_content', content_type='image/png')
response = self.client.post(reverse('upload_pagebg'), {'page_background': image})
data = json.loads(response.content)
self.assertTrue(data['success'])
self.assertIn('bg_url', data)
def test_upload_pagebg_no_file(self):
response = self.client.post(reverse('upload_pagebg'))
data = json.loads(response.content)
self.assertFalse(data['success'])
self.assertEqual(data['message'], '未收到文件')
def test_upload_pagebg_not_logged_in(self):
self.client.logout()
response = self.client.post(reverse('upload_pagebg'))
data = json.loads(response.content)
self.assertFalse(data['success'])
def test_delete_post_not_logged_in(self):
self.client.logout()
response = self.client.post(reverse('delete_post', args=[1]))
self.assertEqual(response.status_code, 302)
def test_delete_post_invalid(self):
response = self.client.post(reverse('delete_post', args=[9999]))
self.assertEqual(response.status_code, 404)

+ 10
- 0
MyPage/urls.py View File

@ -0,0 +1,10 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.my_page_view, name='my_page'),
path('upload-avatar/', views.upload_avatar, name='upload_avatar'),
path('upload-banner/', views.upload_banner, name='upload_banner'),
path('upload-pagebg/', views.upload_page_background, name='upload_pagebg'),
path('delete_post/<int:post_id>/', views.delete_post, name='delete_post'),
]

+ 140
- 0
MyPage/views.py View File

@ -0,0 +1,140 @@
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import ProfileUpdateForm
from .models import UserProfile, Follow
from Community.models import Like, Comment, Post
from users.models import CustomUser
from Schedule.models import Event, Task
from datetime import datetime, timedelta
from django.http import JsonResponse
@login_required(login_url='login')
def my_page_view(request):
# 当前登录用户
user = request.user
profile = user.profile
# 上传、修改资料
if request.method == 'POST':
form = ProfileUpdateForm(request.POST, request.FILES, instance=user)
if form.is_valid():
# 保存 username(avatar 字段不能自动保存)
user.username = form.cleaned_data.get('username', user.username)
if request.FILES.get('avatar'):
user.avatar = request.FILES['avatar'] # ✅ 手动保存头像
user.save()
# 更新 UserProfile 的字段
profile.bio = request.POST.get('bio', '')
if 'personal_background' in request.FILES:
profile.personal_background = request.FILES['personal_background']
if 'page_background' in request.FILES:
profile.page_background = request.FILES['page_background']
profile.save()
return redirect('my_page')
else:
form = ProfileUpdateForm(instance=user)
# 我关注的人
follows = Follow.objects.filter(follower=user).select_related('followed')
# 我的帖子
my_posts = Post.objects.filter(user=user).order_by('-created_at')
# 我的点赞
liked_posts = Post.objects.filter(like__user=user).distinct()
# 我的收藏
favorited_posts = Post.objects.filter(favorite__user=user).distinct()
# 通知:别人点赞/评论了我的帖子
recent_likes = Like.objects.filter(post__user=user).exclude(user=user).select_related('user', 'post').order_by('-created_at')[:10]
recent_comments = Comment.objects.filter(post__user=user).exclude(user=user).select_related('user', 'post').order_by('-created_at')[:10]
# 获取今天以后的最近3条日程
now = datetime.now()
upcoming_events = Event.objects.filter(user=request.user).filter(
date__gt=now.date()
) | Event.objects.filter(
user=request.user,
date=now.date(),
time__gte=now.time()
)
upcoming_events = upcoming_events.order_by('date', 'time')[:3]
# 获取未完成任务(最近添加的3个)
recent_tasks = Task.objects.filter(
user=request.user,
completed=False
).order_by('-created_at')[:3]
return render(request, 'myPage.html', {
'form': form,
'user': user,
'profile': profile,
'follows': follows,
'my_posts': my_posts,
'liked_posts': liked_posts,
'favorited_posts': favorited_posts,
'recent_likes': recent_likes,
'recent_comments': recent_comments,
'upcoming_events': upcoming_events,
'recent_tasks': recent_tasks,
})
# 头像图片上传
def upload_avatar(request):
if request.method == 'POST' and request.user.is_authenticated:
user = request.user
if 'avatar' in request.FILES:
user.avatar = request.FILES['avatar']
user.save()
return JsonResponse({'success': True, 'avatar_url': user.avatar.url})
else:
return JsonResponse({'success': False, 'message': '没有接收到avatar文件'})
return JsonResponse({'success': False, 'message': '请求失败,必须为POST并登录'})
# 个人资料背景上传
def upload_banner(request):
if request.method == 'POST' and request.user.is_authenticated:
profile = request.user.profile
if 'personal_background' in request.FILES:
profile.personal_background = request.FILES['personal_background']
profile.save()
return JsonResponse({'success': True, 'bg_url': profile.personal_background.url})
else:
return JsonResponse({'success': False, 'message': '未收到文件'})
return JsonResponse({'success': False, 'message': '权限或方法错误'})
# 页面背景图片上传
def upload_page_background(request):
if request.method == 'POST' and request.user.is_authenticated:
profile = request.user.profile
if 'page_background' in request.FILES:
profile.page_background = request.FILES['page_background']
profile.save()
return JsonResponse({'success': True, 'bg_url': profile.page_background.url})
else:
return JsonResponse({'success': False, 'message': '未收到文件'})
return JsonResponse({'success': False, 'message': '权限或方法错误'})
# 删除帖子
@login_required(login_url='login')
def delete_post(request, post_id):
post = get_object_or_404(Post, id=post_id, user=request.user)
if request.method == 'POST':
post.delete()
messages.success(request, "帖子已删除!")
return redirect('my_page')

+ 49
- 115
README.md View File

@ -1,149 +1,83 @@
# 📡 WaveControl 隔空手势控制系统
# WaveSign 手语通
> 一套融合**手势识别**与**语音控制**的非接触式人机交互系统,包含主控制平台、手语学习平台 WaveSign、赛车游戏控制模块三大子系统,致力于打造自然、高效、多场景适配的“举手即控”体验
**WaveSign**是一个为听障人群和希望与他们顺畅沟通的用户打造的手语学习平台,集成了手语教学、评分反馈、社区互动、生活服务、日程管理等模块,致力于打破沟通壁垒,构建无声世界与健听社会之间的桥梁
[📃 WaveSign项目需求文档](./WaveSign需求分析文档.md)
[📐 WaveSign测试文档](./WaveSign测试文档.md)
## 项目简介
[🔗 B站完整视频链接](https://www.bilibili.com/video/BV1Fig5zHEhq?vd_source=46a0e2ec60dfb8a247c96905ee47d378)
在厨房、医疗、演讲等“无法触控”或“不便触控”的环境中,传统鼠标/键盘交互模式效率低、操作受限。**WaveControl**以此为切入点,构建了一个基于摄像头识别的隔空控制系统,融合手势识别与语音识别,实现对系统级输入(键盘/鼠标)、手语教学以及游戏控制等功能。
## 项目亮点
项目采用模块化架构设计,包含三大子系统:
- **手语教学与评分系统**:支持上传视频或使用摄像头进行实时手势识别与评分(基于 MediaPipe)
- **互动练习与课程地图**:翻转卡片巩固记忆,任务式解锁式学习体验
- **社区交流**:支持发帖、评论、点赞、关注,打造手语学习分享空间
- **日程管理**:内置日历与待办清单,适配学习与生活规划
- **生活服务整合**
- 出行服务:地图 + 导航 + 实时提醒
- 好物推荐:辅助器具选购
- 就业信息:精选岗位推送
- 活动预告:亲子、技能、文娱等无障碍活动信息
1. **主控制平台**:支持窗口操作、媒体控制、鼠标替代、游戏映射等功能
2. **赛车游戏交互系统**:实现与《Rush Rally Origins》等赛车游戏的隔空手柄交互
3. **WaveSign 手语通**:面向听障人群的手语学习与社区互动平台
## 技术栈
## 测试信息
- **前端**:HTML + CSS + Tailwind CSS + JavaScript
- **后端**:Django 4.x(MTV 架构)
- **数据库**:SQLite3
- **识别引擎**:MediaPipe Hand Landmarker
- **开发工具**:VS Code + Git
本项目配套了完整的[测试文档](./项目测试文档.md),涵盖以下子模块:
- ✅ **主控制系统测试程序**:手势识别 → 键盘鼠标映射 → 交互反馈
- ✅ **游戏控制测试程序**:手势实时识别 → 虚拟手柄信号发送 → 赛车游戏响应验证
- ✅ **手语识别与打分测试程序**:摄像头实时捕捉动作 → MediaPipe评分 → UI动画与文本反馈
- ✅ **用户交互测试**:社区发帖、点赞评论、任务管理、日程提醒等核心功能均有覆盖
测试方式支持浏览器调试 + 控制台运行日志追踪,若遇白屏可通过 Chrome DevTools 检查模块加载或路径引用情况。
## 核心模块
| 模块目录 | 功能描述 |
| -------------- | ------------------------------------------------------------ |
| `Community/` | 手语社区模块:发帖、评论、点赞、标签推荐等互动功能 |
| `Home/` | 首页模块:项目介绍、导航跳转、课程推荐入口 |
| `LifeServing/` | 生活服务模块:整合出行服务、商品推荐、就业信息、近期活动 |
| `media/` | 用户上传内容目录(头像、帖子配图、视频等) |
| `MyPage/` | 个人中心模块:用户资料展示与修改、我的收藏、发布、头像等 |
| `Schedule/` | 日程管理模块:任务清单 + 日历管理功能,适配个人计划 |
| `SignLink/` | 项目主配置目录(`settings.py`, `urls.py`, `wsgi.py` 等) |
| `SLClassroom/` | 手语教室模块:课程学习、视频上传评分、摄像头实时识别、互动练习等 |
| `static/` | 静态资源目录:CSS、JavaScript、图像、模型文件等 |
| `templates/` | 页面模板目录:所有 HTML 文件集中存放 |
| `users/` | 用户系统:注册、登录、退出、自定义用户模型 `CustomUser` 实现 |
## Git 分支说明
| 分支名 | 描述 | 跳转链接 |
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `master` | 主分支,已完成整合,适用于演示与部署 | [🔗 master 分支](https://gitee.com/wydhhh/software-engineering/tree/master/) |
| `finalv1` | 前后端初步融合尝试,手势 → 页面响应逻辑测试阶段 | [🔗 finalv1](https://gitee.com/wydhhh/software-engineering/tree/finalv1/) |
| `finalv2` | 完成手势识别与前端事件联动,页面按钮联动测试 | [🔗 finalv2](https://gitee.com/wydhhh/software-engineering/tree/finalv2/) |
| `finalv3` | 增加语音识别、手势控制切换、音乐控制、手语平台接入、各子系统联调优化 | [🔗 finalv3](https://gitee.com/wydhhh/software-engineering/tree/finalv3/) |
| `gesture` | 手势识别逻辑独立开发模块 | [🔗 gesture](https://gitee.com/wydhhh/software-engineering/tree/gesture/) |
| `gesture_for_chrome` | 针对 Chrome 插件开发的手势控制方案(PPT翻页) | [🔗 gesture_for_chrome](https://gitee.com/wydhhh/software-engineering/tree/gesture_for_chrome/) |
| `gesture-game` | 初步游戏控制实验,控制小球移动 | [🔗 gesture-game](https://gitee.com/wydhhh/software-engineering/tree/gesture-game/) |
| `game_control` | 控制《Rush Rally Origins》赛车游戏,已支持加速转向等 | [🔗 game_control](https://gitee.com/wydhhh/software-engineering/tree/game_control/) |
| `wavesign` | 手语通子系统开发主线,包括教学评分、社区、日程等 | [🔗 wavesign](https://gitee.com/wydhhh/software-engineering/tree/wavesign/) |
| `web` | 最初的网页原型设计,UI 静态草稿 | [🔗 web](https://gitee.com/wydhhh/software-engineering/tree/web/) |
| `screenshot` | 手势控制截屏模块,用于快速抓取操作界面 | [🔗 screenshot](https://gitee.com/wydhhh/software-engineering/tree/screenshot/) |
| `vosk_inc` | 接入 VOSK 实现语音识别与实时字幕展示 | [🔗 vosk_inc](https://gitee.com/wydhhh/software-engineering/tree/vosk_inc/) |
## 启动项目
```bash
python manage.py runserver
```
访问: http://127.0.0.1:8000/
## 技术架构
| 层级 | 技术方案 |
| ------------ | ------------------------------------------------------------ |
| 前端 | vue3 + TypeScript +HTML + CSS + Tailwind CSS + JavaScript + PySide2(Qt GUI) |
| 后端 | Django 4.x(主平台 + 手语通) + Python 脚本逻辑(游戏控制) |
| 手势识别 | MediaPipe Hand Landmarker |
| 虚拟设备控制 | 键盘鼠标模拟、vgamepad 虚拟手柄(XInput) |
| 数据处理 | Kalman Filter(手势抖动滤波)、SQLite3 数据库 |
## 项目预览
![image-20250721224854771](./img/首页.png)
## 模块介绍
![image-20250721223801568](./img/出行服务.png)
### 1️⃣ 主控制平台(WaveControl)
![image-20250721223836503](./img/好物推荐.png)
##### ✌️ **功能特色**
![image-20250721223935112](./img/就业信息.png)
- 多种预设手势操作(点击、滚动、后退等)
- 手势范围调节与自定义手势库
- 支持语音识别辅助控制
- 界面直观,状态反馈实时
![image-20250721224031001](./img/近期活动.png)
##### 🎯 应用场景
![image-20250721224403392](./img/日程管理.png)
- 📺 沙发上追剧时,不再找遥控器,用手势暂停/快进
- 👨‍🏫 教学/演讲中,用手势控制 PPT 流畅翻页
- 🧑‍🍳 厨房做饭时,隔空查食谱不怕弄脏设备
- 🏥 医疗/无菌操作室中,非接触式操作电脑界面
- 🕹️ 游戏中挥手即控,沉浸感倍增
🖼️ **UI 示例**
- 控制主面板(准确率/响应时间/识别窗口)
- 手势管理面板(快捷操作映射设置)
## 仓库部分迭代情况
### 2️⃣ 游戏控制模块
🔗 项目演示:[游戏控制项目演示视频](https://www.bilibili.com/video/BV1H5gLzsEn8?vd_source=46a0e2ec60dfb8a247c96905ee47d378)
🎮 目标:**无需实体手柄,通过摄像头即可玩赛车游戏!**
适配游戏:Steam平台《Rush Rally Origins》及支持 Xbox手柄的其他游戏
**实现要点:**
| 功能 | 技术说明 |
| ------------ | ----------------------------------------------------------- |
| 摄像头识别 | OpenCV + MediaPipe |
| 手势控制映射 | 👍右手拇指上扬 = 加速 👍左手 = 刹车 ✋左倾 = 左转,右倾 = 右转 |
| 虚拟手柄接口 | vgamepad + XInput |
| 抖动滤除 | Kalman 滤波器平滑动作 |
| UI反馈 | PySide2 构建调试窗口 |
### 3️⃣ 手语通子项目:**WaveSign**
🔗 项目演示:[手语通项目演示视频](https://www.bilibili.com/video/BV1Fig5zHEhq?vd_source=46a0e2ec60dfb8a247c96905ee47d378)
项目定位:帮助听障人群及其家人朋友学习、练习、交流手语的综合平台
**功能模块:**
- ✅ **手语教学与评分系统**:上传视频或用摄像头练习手语动作,系统打分反馈
- 🗺️ **课程地图与互动练习**:任务式学习,配合卡片式巩固练习
- 👥 **社区交流**:发帖、评论、点赞、关注等功能
- 📅 **日程管理**:内置待办事项与日历,辅助学习安排
- 🧭 **生活服务**
- 出行导航(结合地图与实时提醒)
- 辅助器具推荐
- 就业信息推送
- 无障碍亲子/技能活动预告
**技术实现:**
- Django + SQLite 构建用户系统与服务逻辑
- 使用 MediaPipe 实时评分用户手语表现
- 前端页面响应式 + 卡片式交互体验
## 项目成员
王云岱 朱子玥 杨嘉莉
## 📌 项目进度
- ✅ 第一轮:系统原型 + UI设计 + 手势识别框架
- ✅ 第二轮:主平台功能实现 + 手势控制实现
- ✅ 第三轮:打通语音识别 + 游戏交互控制 + 手语通平台初步实现
- ✅ 第四轮:赛车游戏交互实现 + 手语通平台完整搭建
- 🧪 第五轮:综合测试 + 用户体验调优 + 结项演示
![image-20250722012217662](./img/仓库迭代情况.png)

+ 0
- 0
SLClassroom/__init__.py View File


+ 3
- 0
SLClassroom/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
SLClassroom/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class SlclassroomConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "SLClassroom"

+ 0
- 0
SLClassroom/migrations/__init__.py View File


+ 3
- 0
SLClassroom/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 10
- 0
SLClassroom/tests.py View File

@ -0,0 +1,10 @@
from django.test import TestCase, Client
from django.urls import reverse
# Create your tests here.
class SLClassroomViewTest(TestCase):
def test_sl_classroom_page(self):
client = Client()
response = client.get(reverse('sl_classroom'))
self.assertEqual(response.status_code, 200)

+ 6
- 0
SLClassroom/urls.py View File

@ -0,0 +1,6 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='sl_classroom'),
]

+ 6
- 0
SLClassroom/views.py View File

@ -0,0 +1,6 @@
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'SLClassroom.html')

+ 0
- 0
Schedule/__init__.py View File


+ 3
- 0
Schedule/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
Schedule/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ScheduleConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "Schedule"

+ 49
- 0
Schedule/migrations/0001_initial.py View File

@ -0,0 +1,49 @@
# Generated by Django 5.2 on 2025-05-30 01:17
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Event",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=200)),
("date", models.DateField()),
("time", models.TimeField()),
("description", models.TextField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name="Task",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("text", models.CharField(max_length=200)),
("completed", models.BooleanField(default=False)),
("created_at", models.DateTimeField(auto_now_add=True)),
],
),
]

+ 47
- 0
Schedule/migrations/0002_initial.py View File

@ -0,0 +1,47 @@
# Generated by Django 5.2 on 2025-05-30 01:17
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("Schedule", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name="event",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="events",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="task",
name="event",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="tasks",
to="Schedule.event",
),
),
migrations.AddField(
model_name="task",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="tasks",
to=settings.AUTH_USER_MODEL,
),
),
]

+ 0
- 0
Schedule/migrations/__init__.py View File


+ 26
- 0
Schedule/models.py View File

@ -0,0 +1,26 @@
# schedule/models.py
from django.db import models
from django.contrib.auth.models import User
from WaveSign import settings
class Event(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='events')
title = models.CharField(max_length=200)
date = models.DateField()
time = models.TimeField()
description = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Task(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='tasks')
text = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
event = models.ForeignKey(Event, on_delete=models.SET_NULL, blank=True, null=True, related_name='tasks')
def __str__(self):
return self.text

+ 15
- 0
Schedule/serializers.py View File

@ -0,0 +1,15 @@
# schedule/serializers.py
from rest_framework import serializers # type: ignore
from .models import Event, Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ['id', 'text', 'completed', 'created_at', 'event']
class EventSerializer(serializers.ModelSerializer):
tasks = TaskSerializer(many=True, read_only=True)
class Meta:
model = Event
fields = ['id', 'title', 'date', 'time', 'description', 'created_at', 'tasks']

+ 65
- 0
Schedule/tests.py View File

@ -0,0 +1,65 @@
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from .models import Event, Task
from rest_framework.test import APIClient
import json
User = get_user_model()
class EventModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser', password='testpass')
self.event = Event.objects.create(user=self.user, title='Test Event', date='2025-01-01', time='12:00', description='desc')
def test_str(self):
self.assertEqual(str(self.event), 'Test Event')
class TaskModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser2', password='testpass')
self.event = Event.objects.create(user=self.user, title='Test Event', date='2025-01-01', time='12:00', description='desc')
self.task = Task.objects.create(user=self.user, text='Test Task', event=self.event)
def test_str(self):
self.assertEqual(str(self.task), 'Test Task')
class ScheduleApiTest(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(username='testuser3', password='testpass')
self.client.login(username='testuser3', password='testpass')
def test_event_list_api(self):
response = self.client.get(reverse('event-list'))
self.assertIn(response.status_code, [200, 403, 401])
class ScheduleViewsTest(TestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_user(username='testuser4', password='testpass')
self.client.force_authenticate(user=self.user)
self.event = Event.objects.create(user=self.user, title='Event', date='2025-01-01', time='12:00', description='desc')
self.task = Task.objects.create(user=self.user, text='Task', event=self.event)
def test_event_list_unauthenticated(self):
self.client.force_authenticate(user=None)
response = self.client.get(reverse('event-list'))
self.assertEqual(response.status_code, 401)
def test_event_detail_not_exist(self):
response = self.client.get(reverse('event-detail', args=[9999]))
self.assertEqual(response.status_code, 404)
def test_task_toggle_complete_not_exist(self):
response = self.client.post(reverse('task-toggle', args=[9999]))
self.assertEqual(response.status_code, 404)
def test_task_delete_not_exist(self):
response = self.client.delete(reverse('task-delete', args=[9999]))
self.assertEqual(response.status_code, 404)
def test_today_events_unauthenticated(self):
self.client.force_authenticate(user=None)
response = self.client.get(reverse('today-events'))
self.assertEqual(response.status_code, 401)

+ 20
- 0
Schedule/urls.py View File

@ -0,0 +1,20 @@
# Schedule/urls.py
from django.urls import path
from .views import (
EventListCreateView, EventDetailView, ScheduleView,
TaskListCreateView, TaskToggleCompleteView, TaskDeleteView,
TodayEventsView
)
urlpatterns = [
# 事件API
path('events/', EventListCreateView.as_view(), name='event-list'),
path('events/<int:pk>/', EventDetailView.as_view(), name='event-detail'),
path('events/today/', TodayEventsView.as_view(), name='today-events'),
# 任务API
path('tasks/', TaskListCreateView.as_view(), name='task-list'),
path('tasks/<int:pk>/toggle/', TaskToggleCompleteView.as_view(), name='task-toggle'),
path('tasks/<int:pk>/delete/', TaskDeleteView.as_view(), name='task-delete'),
path('', ScheduleView.as_view(), name='schedule'),
]

+ 94
- 0
Schedule/views.py View File

@ -0,0 +1,94 @@
# schedule/views.py
from rest_framework import generics, status # type: ignore
from rest_framework.response import Response # type: ignore
from rest_framework.permissions import IsAuthenticated # type: ignore
from rest_framework.views import APIView # type: ignore
from django.shortcuts import get_object_or_404
from django.utils import timezone
from .models import Event, Task
from .serializers import EventSerializer, TaskSerializer
from django.shortcuts import render
from django.views.generic import TemplateView
class EventListCreateView(generics.ListCreateAPIView):
serializer_class = EventSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
# 获取日期范围参数
start_date = self.request.query_params.get('start_date')
end_date = self.request.query_params.get('end_date')
queryset = Event.objects.filter(user=self.request.user)
# 如果提供了日期范围,进行过滤
if start_date and end_date:
queryset = queryset.filter(date__range=[start_date, end_date])
# 按日期和时间排序
return queryset.order_by('date', 'time')
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class EventDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Event.objects.all()
serializer_class = EventSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Event.objects.filter(user=self.request.user)
class TaskListCreateView(generics.ListCreateAPIView):
serializer_class = TaskSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
# 如果提供了date参数,过滤当天的任务
date = self.request.query_params.get('date')
if date:
return Task.objects.filter(user=self.request.user, event__date=date)
# 默认返回所有任务
return Task.objects.filter(user=self.request.user)
def perform_create(self, serializer):
# 如果请求中包含event_id,关联到对应的事件
event_id = self.request.data.get('event')
if event_id:
try:
event = Event.objects.get(id=event_id, user=self.request.user)
serializer.save(user=self.request.user, event=event)
except Event.DoesNotExist:
return Response({"error": "Event not found"}, status=status.HTTP_400_BAD_REQUEST)
else:
serializer.save(user=self.request.user)
class TaskToggleCompleteView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk):
task = get_object_or_404(Task, id=pk, user=request.user)
task.completed = not task.completed
task.save()
serializer = TaskSerializer(task)
return Response(serializer.data)
class TaskDeleteView(generics.DestroyAPIView):
queryset = Task.objects.all()
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Task.objects.filter(user=self.request.user)
class TodayEventsView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
today = timezone.now().date()
events = Event.objects.filter(user=request.user, date=today)
serializer = EventSerializer(events, many=True)
return Response(serializer.data)
class ScheduleView(TemplateView):
template_name = 'Schedule.html'

+ 0
- 0
WaveSign/__init__.py View File


+ 16
- 0
WaveSign/asgi.py View File

@ -0,0 +1,16 @@
"""
ASGI config for WaveSign project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "WaveSign.settings")
application = get_asgi_application()

+ 168
- 0
WaveSign/settings.py View File

@ -0,0 +1,168 @@
"""
Django settings for WaveSign project.
Generated by 'django-admin startproject' using Django 5.2.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-%%%e21!*1kab78@vn+r=3qm%kg+cbek)$m7ha1+240nub#ipq^"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
AUTH_USER_MODEL = 'users.CustomUser'
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# 'users', # 用户模块
'SLClassroom', # 手语教室
'LifeServing', # 生活服务
'Community', # 社区模块
# 'Schedule', # 日程
'MyPage', # 我的页面
'Home', # 主页
'users.apps.UsersConfig', # 登录信号
'Schedule.apps.ScheduleConfig',
'rest_framework',
'rest_framework_simplejwt',
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "WaveSign.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
'DIRS': [os.path.join(BASE_DIR, 'templates')],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "WaveSign.wsgi.application"
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'), # 添加这行,告诉 Django 去哪里找静态文件
]
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# mypage的图像上传逻辑
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
from datetime import timedelta
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
}

+ 22
- 0
WaveSign/urls.py View File

@ -0,0 +1,22 @@
from django.contrib import admin
from django.urls import path
from WaveSign import views # 从 views 导入视图函数
from django.conf.urls import include
from users.views import register_view
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('Home.urls')), # 默认首页
path('SLClassroom/', include('SLClassroom.urls')), # 手语教室
path('LifeServing/', include('LifeServing.urls')), # 生活服务
path('Community/', include('Community.urls')), # 社区
path('Schedule/', include('Schedule.urls')), # 日程
path('MyPage/', include('MyPage.urls')), # 我的页面
path('users/', include('users.urls')), # 用户
]
# 👇 添加这句以支持开发环境下媒体文件访问
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ 10
- 0
WaveSign/views.py View File

@ -0,0 +1,10 @@
from django.shortcuts import render
def index(request):
return render(request, 'Home.html') # 渲染模板
def login_view(request):
"""渲染Login.html页面"""
return render(request, 'Login.html')
def register_view(request):
"""渲染Register.html页面"""
return render(request, 'Register.html')

+ 16
- 0
WaveSign/wsgi.py View File

@ -0,0 +1,16 @@
"""
WSGI config for WaveSign project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "WaveSign.settings")
application = get_wsgi_application()

+ 268
- 0
WaveSign测试文档.md View File

@ -0,0 +1,268 @@
# WaveSign 项目自动化测试文档
> **编写日期**:2025-07-21
> **编写人**:杨嘉莉
> **适用范围**:Django 后端项目全模块,含 API、模型、视图、用户逻辑等
------
## 📄 文档说明
本测试文档系统性描述了 WaveSign 项目的测试策略、用例设计、运行过程、覆盖率统计及维护建议,适用于团队协作、质量评估与交付归档。
> 📸 以下为测试执行与覆盖率报告截图:
![image-20250722191111792](./img/testOK.png)
*图1:Django 全部 31 个测试用例成功运行*
![image-20250722191224973](./img/test覆盖率93%.png)
*图2:coverage HTML 报告展示总覆盖率为 93%*
------
## 一、测试设计
### 1.1 测试目标
- 验证各业务模块的主要功能、异常分支、权限控制、数据完整性等是否符合预期。
- 保证系统在正常和异常情况下均能稳定运行,防止回归和低级错误。
- 达到并保持85%以上的代码覆盖率,优先覆盖所有核心业务分支。
### 1.2 测试策略
- **单元测试**:对每个模型、表单、序列化器、视图函数/类进行最小粒度的功能验证。
- **集成测试**:对视图、API接口的正常流程、异常分支、权限控制等进行端到端验证。
- **异常与边界测试**:覆盖所有常见的无效输入、权限不足、重复操作、数据不存在等情况。
- **回归测试**:每次主要功能变更后,自动运行全部测试,确保无回归。
### 1.3 测试工具
- **pytest**、**pytest-django**、**pytest-cov**:主力测试与覆盖率工具
- **Django TestCase**、**APIClient**:Django自带测试框架与REST接口测试
- **coverage**:生成详细的覆盖率报告
------
## 二、测试用例设计与说明
### 2.1 测试用例说明(汇总表)
| 用例编号 | 模块 | 测试内容/场景 | 预期结果/断言 |
| -------- | ----------- | ---------------------------- | ----------------------------- |
| 2.1.1 | Community | 创建帖子(内容正常) | 状态码302,帖子被创建 |
| 2.1.2 | Community | 创建帖子(内容为空) | 状态码302,未创建 |
| 2.1.3 | Community | 点赞帖子(正常) | 状态码200,点赞数+1 |
| 2.1.4 | Community | 点赞帖子(重复点赞) | JSON返回已点赞 |
| 2.1.5 | Community | 点赞不存在的帖子 | 状态码404,JSON返回帖子不存在 |
| 2.1.6 | Community | 评论帖子(正常) | 状态码200,评论数+1 |
| 2.1.7 | Community | 评论帖子(内容为空) | JSON返回评论不能为空 |
| 2.1.8 | Community | 评论不存在的帖子 | 状态码404,JSON返回帖子不存在 |
| 2.1.9 | Community | 收藏帖子(正常) | 状态码200,收藏数+1 |
| 2.1.10 | Community | 收藏帖子(重复收藏) | JSON返回已收藏 |
| 2.1.11 | Community | 收藏不存在的帖子 | 状态码404,JSON返回帖子不存在 |
| 2.1.12 | Community | 关注他人(正常/取消关注) | JSON返回关注/取消关注 |
| 2.1.13 | Community | 关注自己 | JSON返回不能关注自己 |
| 2.1.14 | Community | 关注不存在的用户 | JSON返回用户不存在 |
| 2.1.15 | Community | 未登录访问受保护视图 | 状态码302重定向 |
| 2.2.1 | MyPage | 个人中心访问(登录) | 状态码200 |
| 2.2.2 | MyPage | 个人中心访问(未登录) | 状态码302重定向 |
| 2.2.3 | MyPage | 资料修改(POST) | 状态码200/302,资料被修改 |
| 2.2.4 | MyPage | 头像上传(成功) | JSON返回success,含avatar_url |
| 2.2.5 | MyPage | 头像上传(无文件) | JSON返回失败,message提示 |
| 2.2.6 | MyPage | 头像上传(未登录) | JSON返回失败 |
| 2.2.7 | MyPage | 资料背景上传(成功) | JSON返回success,含bg_url |
| 2.2.8 | MyPage | 资料背景上传(无文件) | JSON返回失败,message提示 |
| 2.2.9 | MyPage | 资料背景上传(未登录) | JSON返回失败 |
| 2.2.10 | MyPage | 页面背景上传(成功) | JSON返回success,含bg_url |
| 2.2.11 | MyPage | 页面背景上传(无文件) | JSON返回失败,message提示 |
| 2.2.12 | MyPage | 页面背景上传(未登录) | JSON返回失败 |
| 2.2.13 | MyPage | 删除帖子(未登录) | 状态码302重定向 |
| 2.2.14 | MyPage | 删除帖子(无效ID) | 状态码404 |
| 2.3.1 | Schedule | 事件列表API(已登录) | 状态码200,返回事件列表 |
| 2.3.2 | Schedule | 事件列表API(未登录) | 状态码401 |
| 2.3.3 | Schedule | 事件详情API(不存在ID) | 状态码404 |
| 2.3.4 | Schedule | 任务切换完成状态(不存在ID) | 状态码404 |
| 2.3.5 | Schedule | 任务删除(不存在ID) | 状态码404 |
| 2.3.6 | Schedule | 今日事件API(未登录) | 状态码401 |
| 2.4.1 | users | 注册(成功) | 状态码200/302,用户被创建 |
| 2.4.2 | users | 注册(用户名已存在) | 状态码200/302,注册失败 |
| 2.4.3 | users | 注册(邮箱已存在) | 状态码200/302,注册失败 |
| 2.4.4 | users | 注册(密码不一致) | 状态码200/302,注册失败 |
| 2.4.5 | users | 登录(成功) | 状态码200/302,登录成功 |
| 2.4.6 | users | 登录(用户名不存在) | 状态码200/302,登录失败 |
| 2.4.7 | users | 登录(密码错误) | 状态码200/302,登录失败 |
| 2.4.8 | users | 登出 | 状态码302 |
| 2.5.1 | Home | 匿名用户访问首页 | 状态码200 |
| 2.5.2 | Home | 登录用户访问首页 | 状态码200 |
| 2.5.3 | LifeServing | 匿名用户访问生活服务首页 | 状态码200 |
| 2.5.4 | LifeServing | 登录用户访问生活服务首页 | 状态码200 |
| 2.5.5 | SLClassroom | 匿名用户访问手语教室首页 | 状态码200 |
| 2.5.6 | SLClassroom | 登录用户访问手语教室首页 | 状态码200 |
---
**说明:**
- 用例编号与模块编号对应文档结构,便于追溯。
- 断言内容可根据实际业务和前端需求进一步细化。
- 具体实现见各模块 `tests.py` 文件。
### 2.2 模块结构说明
#### 📁 Community
- 帖子创建、点赞、评论、收藏、关注逻辑测试
- 含异常路径与未登录验证
#### 📁 MyPage
- 用户资料修改、头像/背景图上传
- 权限控制 + 上传边界用例
#### 📁 Schedule
- 任务/事件 API 的增删改查、状态切换、未登录场景
#### 📁 users
- 注册、登录、登出功能验证,字段约束、重复用户校验
#### 📁 Home / LifeServing / SLClassroom
- 首页匿名访问/登录访问检查,静态页面加载
------
## 三、测试执行与结果
### 3.1 运行命令
```bash
pip install pytest pytest-django coverage
coverage run manage.py test
coverage report
coverage html # 查看 htmlcov/index.html
```
### 3.2 测试结果概览
| 指标项 | 数据值 |
| ---------- | ---------- |
| 总用例数 | 31 |
| 执行耗时 | 15.9s |
| 执行结果 | 全部通过 ✅ |
| 覆盖率报告 | `htmlcov/` |
| 覆盖率总览 | 93% ✅ |
### 3.3 覆盖率示意(核心模块)
#### 主要覆盖率分布
| 文件/模块 | 语句数 | 未覆盖 | 覆盖率 |
| -------------- | ------ | ------ | ------ |
| Community/ | 248 | 13 | 87% |
| MyPage/ | 209 | 19 | 91% |
| Schedule/ | 172 | 22 | 87% |
| users/ | 109 | 5 | 95% |
| 其他(Home等) | 26 | 0 | 100% |
| **总计** | 916 | 64 | 93% |
------
## 四、典型测试用例示例
### Community/tests.py
```python
def test_create_post_with_content(self):
self.client.login(username='testuser', password='testpass')
response = self.client.post(reverse('create_post'), {'content': 'new post'})
self.assertEqual(response.status_code, 302)
def test_like_post_not_exist(self):
self.client.login(username='testuser', password='testpass')
response = self.client.post(reverse('like_post', args=[9999]))
self.assertEqual(response.status_code, 404)
data = json.loads(response.content)
self.assertEqual(data['error'], '帖子不存在')
```
### MyPage/tests.py
```python
def test_upload_avatar_no_file(self):
self.client.login(username='testuser', password='testpass')
response = self.client.post(reverse('upload_avatar'))
data = json.loads(response.content)
self.assertFalse(data['success'])
self.assertEqual(data['message'], '没有接收到avatar文件')
```
### Schedule/tests.py
```python
def test_event_list_unauthenticated(self):
self.client.force_authenticate(user=None)
response = self.client.get(reverse('event-list'))
self.assertEqual(response.status_code, 401)
```
### users/tests.py
```python
def test_register_password_mismatch(self):
response = self.client.post(reverse('register'), {
'username': 'newuser',
'email': 'new@example.com',
'password': 'pass1',
'password_confirm': 'pass2',
'agreed_terms': True
})
self.assertIn(response.status_code, [200, 302])
```
## 五、结论与建议
- ✅ 系统功能测试通过,覆盖关键模块逻辑,质量稳定
- ✅ 总覆盖率 93%,高于目标线 85%
- ✅ 所有视图与模型功能均已涵盖典型异常路径
------
## 六、维护与扩展建议
- 每次新增功能后请 **同步添加测试**
- 保持高覆盖率,关注 HTML 报告中标红行
- 使用命名规范:`test_模块_功能_场景`
- CI/CD 流程建议强制执行测试(见下文)
------
## 八、文档版本控制
| 版本 | 说明 | 日期 | 作者 |
| ---- | -------------------------------- | ---------- | ----------- |
| v1.0 | 初版,整理所有模块测试+覆盖率93% | 2025-07-21 | jialiyang ✅ |
## ✅ 附件说明
- `htmlcov/`:HTML 覆盖率报告目录
- `img/testOK.png`:控制台测试通过截图
- `img/test覆盖率93%.png`:测试覆盖率报告截图
------
> 📌 **备注**:本文档建议随代码版本维护,并纳入版本控制系统,如 Git。

+ 103
- 0
WaveSign需求分析文档.md View File

@ -0,0 +1,103 @@
# WaveSign手语通需求分析文档
## 1. 项目概述
### 1.1 愿景
构建无障碍沟通平台,连接听障群体与健听社会,通过技术创新消除沟通壁垒。
### 1.2 核心目标
- 提供专业级手语学习与评价系统
- 搭建听障用户生活服务生态系统
- 创建手语社交互动社区
- 建立个人化学习规划体系
- 实现健听人群无障碍沟通支持
### 1.3 项目整体需求分析思维导图
![image-20250722013041510](./img/需求分析思维导图.png)
## 2. 用户分析
### 2.1 目标用户
| 用户类型 | 核心需求 | 使用场景 |
| ---------- | -------------------------------- | ---------------------------------- |
| 听障人士 | 手语表达提升、无障碍生活服务获取 | 日常沟通、求职、出行、社交活动 |
| 健听学习者 | 系统化手语学习、交流实践 | 手语专业学习、志愿者服务、亲友交流 |
| 助残机构 | 服务分发、社群组织 | 活动组织、就业对接、物资援助 |
## 3. 功能需求规格
### 3.1 核心教学模块(SLClassroom)
![image-20250722013541696](/Users/jialiyang/Library/Application Support/typora-user-images/image-20250722013541696.png)
**详细需求:**
- 支持基础手语词库教学
- 手势识别准确率≥95%
- 视频分析响应时间<3秒
- 评分包含:动作完整度、手部位置、动作轨迹
### 3.2 社区互动(Community)
**功能矩阵:**
| 功能模块 | 子功能 | 交互需求 |
| -------- | --------------------------------- | ----------------------------------------------------- |
| 内容发布 | 图文/视频发布 话题标签 位置标注 | 支持手语视频直接发布 AI标签推荐 无障碍地点标识 |
| 社交互动 | 评论/点赞 关注/私信 话题圈 | 表情符号翻译功能 震动提示系统 主题分区管理 |
| 内容生态 | 热门推荐 精华榜单 审核机制 | 个性化内容推荐 每周热榜自动生成 敏感词过滤+人工审核 |
### 3.3 生活服务整合(LifeServing)
1. **出行导航**
- 无障碍路线规划(电梯/坡道优先)
- 公交到站震动提醒
- 紧急联系人自动通知
2. **就业服务**
- 残障友好企业认证体系
- 职位匹配度评分(根据技能标签)
- 视频简历创建工具
3. **好物推荐**
- 智能助听设备评测
- 手语学习辅助工具
- 用户体验UGC社区
4. **活动平台**
- 无障碍活动日历
- 在线报名系统
- 活动提醒服务
### 3.4 日程管理(Schedule)
- **多视图日历**:日/周/月/列表视图
- 自定义日程待办:
- 学习任务提醒
- 活动前序提醒(路线规划+准备事项)
- 周期性日程模板
- 数据看板:
- 学习进度
- 任务完成率统计
- 习惯养成追踪
## 4. 技术约束
1. 开发框架:
- Django 4.x (Python≥3.8)
- 前端Tailwind CSS响应式布局
2. 识别引擎:
- MediaPipe实时手部关键点检测
- 自定义手势识别模型(H5格式)
3. 部署要求:
- 最小硬件:4核CPU/8GB内存
- 视频处理专用GPU推荐
- SQLite→PostgreSQL生产迁移路径
------
**版本控制**
- 文档版本:V1.2
- 更新日期:2025-07-22

BIN
db.sqlite3 View File


+ 1
- 0
htmlcov/.gitignore View File

@ -0,0 +1 @@
# Created by coverage.py

+ 1147
- 0
htmlcov/class_index.html
File diff suppressed because it is too large
View File


+ 733
- 0
htmlcov/coverage_html_cb_6fb7b396.js View File

@ -0,0 +1,733 @@
// Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
// For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
// Coverage.py HTML report browser code.
/*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */
/*global coverage: true, document, window, $ */
coverage = {};
// General helpers
function debounce(callback, wait) {
let timeoutId = null;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
callback.apply(this, args);
}, wait);
};
};
function checkVisible(element) {
const rect = element.getBoundingClientRect();
const viewBottom = Math.max(document.documentElement.clientHeight, window.innerHeight);
const viewTop = 30;
return !(rect.bottom < viewTop || rect.top >= viewBottom);
}
function on_click(sel, fn) {
const elt = document.querySelector(sel);
if (elt) {
elt.addEventListener("click", fn);
}
}
// Helpers for table sorting
function getCellValue(row, column = 0) {
const cell = row.cells[column] // nosemgrep: eslint.detect-object-injection
if (cell.childElementCount == 1) {
var child = cell.firstElementChild;
if (child.tagName === "A") {
child = child.firstElementChild;
}
if (child instanceof HTMLDataElement && child.value) {
return child.value;
}
}
return cell.innerText || cell.textContent;
}
function rowComparator(rowA, rowB, column = 0) {
let valueA = getCellValue(rowA, column);
let valueB = getCellValue(rowB, column);
if (!isNaN(valueA) && !isNaN(valueB)) {
return valueA - valueB;
}
return valueA.localeCompare(valueB, undefined, {numeric: true});
}
function sortColumn(th) {
// Get the current sorting direction of the selected header,
// clear state on other headers and then set the new sorting direction.
const currentSortOrder = th.getAttribute("aria-sort");
[...th.parentElement.cells].forEach(header => header.setAttribute("aria-sort", "none"));
var direction;
if (currentSortOrder === "none") {
direction = th.dataset.defaultSortOrder || "ascending";
}
else if (currentSortOrder === "ascending") {
direction = "descending";
}
else {
direction = "ascending";
}
th.setAttribute("aria-sort", direction);
const column = [...th.parentElement.cells].indexOf(th)
// Sort all rows and afterwards append them in order to move them in the DOM.
Array.from(th.closest("table").querySelectorAll("tbody tr"))
.sort((rowA, rowB) => rowComparator(rowA, rowB, column) * (direction === "ascending" ? 1 : -1))
.forEach(tr => tr.parentElement.appendChild(tr));
// Save the sort order for next time.
if (th.id !== "region") {
let th_id = "file"; // Sort by file if we don't have a column id
let current_direction = direction;
const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE);
if (stored_list) {
({th_id, direction} = JSON.parse(stored_list))
}
localStorage.setItem(coverage.INDEX_SORT_STORAGE, JSON.stringify({
"th_id": th.id,
"direction": current_direction
}));
if (th.id !== th_id || document.getElementById("region")) {
// Sort column has changed, unset sorting by function or class.
localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({
"by_region": false,
"region_direction": current_direction
}));
}
}
else {
// Sort column has changed to by function or class, remember that.
localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({
"by_region": true,
"region_direction": direction
}));
}
}
// Find all the elements with data-shortcut attribute, and use them to assign a shortcut key.
coverage.assign_shortkeys = function () {
document.querySelectorAll("[data-shortcut]").forEach(element => {
document.addEventListener("keypress", event => {
if (event.target.tagName.toLowerCase() === "input") {
return; // ignore keypress from search filter
}
if (event.key === element.dataset.shortcut) {
element.click();
}
});
});
};
// Create the events for the filter box.
coverage.wire_up_filter = function () {
// Populate the filter and hide100 inputs if there are saved values for them.
const saved_filter_value = localStorage.getItem(coverage.FILTER_STORAGE);
if (saved_filter_value) {
document.getElementById("filter").value = saved_filter_value;
}
const saved_hide100_value = localStorage.getItem(coverage.HIDE100_STORAGE);
if (saved_hide100_value) {
document.getElementById("hide100").checked = JSON.parse(saved_hide100_value);
}
// Cache elements.
const table = document.querySelector("table.index");
const table_body_rows = table.querySelectorAll("tbody tr");
const no_rows = document.getElementById("no_rows");
// Observe filter keyevents.
const filter_handler = (event => {
// Keep running total of each metric, first index contains number of shown rows
const totals = new Array(table.rows[0].cells.length).fill(0);
// Accumulate the percentage as fraction
totals[totals.length - 1] = { "numer": 0, "denom": 0 }; // nosemgrep: eslint.detect-object-injection
var text = document.getElementById("filter").value;
// Store filter value
localStorage.setItem(coverage.FILTER_STORAGE, text);
const casefold = (text === text.toLowerCase());
const hide100 = document.getElementById("hide100").checked;
// Store hide value.
localStorage.setItem(coverage.HIDE100_STORAGE, JSON.stringify(hide100));
// Hide / show elements.
table_body_rows.forEach(row => {
var show = false;
// Check the text filter.
for (let column = 0; column < totals.length; column++) {
cell = row.cells[column];
if (cell.classList.contains("name")) {
var celltext = cell.textContent;
if (casefold) {
celltext = celltext.toLowerCase();
}
if (celltext.includes(text)) {
show = true;
}
}
}
// Check the "hide covered" filter.
if (show && hide100) {
const [numer, denom] = row.cells[row.cells.length - 1].dataset.ratio.split(" ");
show = (numer !== denom);
}
if (!show) {
// hide
row.classList.add("hidden");
return;
}
// show
row.classList.remove("hidden");
totals[0]++;
for (let column = 0; column < totals.length; column++) {
// Accumulate dynamic totals
cell = row.cells[column] // nosemgrep: eslint.detect-object-injection
if (cell.classList.contains("name")) {
continue;
}
if (column === totals.length - 1) {
// Last column contains percentage
const [numer, denom] = cell.dataset.ratio.split(" ");
totals[column]["numer"] += parseInt(numer, 10); // nosemgrep: eslint.detect-object-injection
totals[column]["denom"] += parseInt(denom, 10); // nosemgrep: eslint.detect-object-injection
}
else {
totals[column] += parseInt(cell.textContent, 10); // nosemgrep: eslint.detect-object-injection
}
}
});
// Show placeholder if no rows will be displayed.
if (!totals[0]) {
// Show placeholder, hide table.
no_rows.style.display = "block";
table.style.display = "none";
return;
}
// Hide placeholder, show table.
no_rows.style.display = null;
table.style.display = null;
const footer = table.tFoot.rows[0];
// Calculate new dynamic sum values based on visible rows.
for (let column = 0; column < totals.length; column++) {
// Get footer cell element.
const cell = footer.cells[column]; // nosemgrep: eslint.detect-object-injection
if (cell.classList.contains("name")) {
continue;
}
// Set value into dynamic footer cell element.
if (column === totals.length - 1) {
// Percentage column uses the numerator and denominator,
// and adapts to the number of decimal places.
const match = /\.([0-9]+)/.exec(cell.textContent);
const places = match ? match[1].length : 0;
const { numer, denom } = totals[column]; // nosemgrep: eslint.detect-object-injection
cell.dataset.ratio = `${numer} ${denom}`;
// Check denom to prevent NaN if filtered files contain no statements
cell.textContent = denom
? `${(numer * 100 / denom).toFixed(places)}%`
: `${(100).toFixed(places)}%`;
}
else {
cell.textContent = totals[column]; // nosemgrep: eslint.detect-object-injection
}
}
});
document.getElementById("filter").addEventListener("input", debounce(filter_handler));
document.getElementById("hide100").addEventListener("input", debounce(filter_handler));
// Trigger change event on setup, to force filter on page refresh
// (filter value may still be present).
document.getElementById("filter").dispatchEvent(new Event("input"));
document.getElementById("hide100").dispatchEvent(new Event("input"));
};
coverage.FILTER_STORAGE = "COVERAGE_FILTER_VALUE";
coverage.HIDE100_STORAGE = "COVERAGE_HIDE100_VALUE";
// Set up the click-to-sort columns.
coverage.wire_up_sorting = function () {
document.querySelectorAll("[data-sortable] th[aria-sort]").forEach(
th => th.addEventListener("click", e => sortColumn(e.target))
);
// Look for a localStorage item containing previous sort settings:
let th_id = "file", direction = "ascending";
const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE);
if (stored_list) {
({th_id, direction} = JSON.parse(stored_list));
}
let by_region = false, region_direction = "ascending";
const sorted_by_region = localStorage.getItem(coverage.SORTED_BY_REGION);
if (sorted_by_region) {
({
by_region,
region_direction
} = JSON.parse(sorted_by_region));
}
const region_id = "region";
if (by_region && document.getElementById(region_id)) {
direction = region_direction;
}
// If we are in a page that has a column with id of "region", sort on
// it if the last sort was by function or class.
let th;
if (document.getElementById(region_id)) {
th = document.getElementById(by_region ? region_id : th_id);
}
else {
th = document.getElementById(th_id);
}
th.setAttribute("aria-sort", direction === "ascending" ? "descending" : "ascending");
th.click()
};
coverage.INDEX_SORT_STORAGE = "COVERAGE_INDEX_SORT_2";
coverage.SORTED_BY_REGION = "COVERAGE_SORT_REGION";
// Loaded on index.html
coverage.index_ready = function () {
coverage.assign_shortkeys();
coverage.wire_up_filter();
coverage.wire_up_sorting();
on_click(".button_prev_file", coverage.to_prev_file);
on_click(".button_next_file", coverage.to_next_file);
on_click(".button_show_hide_help", coverage.show_hide_help);
};
// -- pyfile stuff --
coverage.LINE_FILTERS_STORAGE = "COVERAGE_LINE_FILTERS";
coverage.pyfile_ready = function () {
// If we're directed to a particular line number, highlight the line.
var frag = location.hash;
if (frag.length > 2 && frag[1] === "t") {
document.querySelector(frag).closest(".n").classList.add("highlight");
coverage.set_sel(parseInt(frag.substr(2), 10));
}
else {
coverage.set_sel(0);
}
on_click(".button_toggle_run", coverage.toggle_lines);
on_click(".button_toggle_mis", coverage.toggle_lines);
on_click(".button_toggle_exc", coverage.toggle_lines);
on_click(".button_toggle_par", coverage.toggle_lines);
on_click(".button_next_chunk", coverage.to_next_chunk_nicely);
on_click(".button_prev_chunk", coverage.to_prev_chunk_nicely);
on_click(".button_top_of_page", coverage.to_top);
on_click(".button_first_chunk", coverage.to_first_chunk);
on_click(".button_prev_file", coverage.to_prev_file);
on_click(".button_next_file", coverage.to_next_file);
on_click(".button_to_index", coverage.to_index);
on_click(".button_show_hide_help", coverage.show_hide_help);
coverage.filters = undefined;
try {
coverage.filters = localStorage.getItem(coverage.LINE_FILTERS_STORAGE);
} catch(err) {}
if (coverage.filters) {
coverage.filters = JSON.parse(coverage.filters);
}
else {
coverage.filters = {run: false, exc: true, mis: true, par: true};
}
for (cls in coverage.filters) {
coverage.set_line_visibilty(cls, coverage.filters[cls]); // nosemgrep: eslint.detect-object-injection
}
coverage.assign_shortkeys();
coverage.init_scroll_markers();
coverage.wire_up_sticky_header();
document.querySelectorAll("[id^=ctxs]").forEach(
cbox => cbox.addEventListener("click", coverage.expand_contexts)
);
// Rebuild scroll markers when the window height changes.
window.addEventListener("resize", coverage.build_scroll_markers);
};
coverage.toggle_lines = function (event) {
const btn = event.target.closest("button");
const category = btn.value
const show = !btn.classList.contains("show_" + category);
coverage.set_line_visibilty(category, show);
coverage.build_scroll_markers();
coverage.filters[category] = show;
try {
localStorage.setItem(coverage.LINE_FILTERS_STORAGE, JSON.stringify(coverage.filters));
} catch(err) {}
};
coverage.set_line_visibilty = function (category, should_show) {
const cls = "show_" + category;
const btn = document.querySelector(".button_toggle_" + category);
if (btn) {
if (should_show) {
document.querySelectorAll("#source ." + category).forEach(e => e.classList.add(cls));
btn.classList.add(cls);
}
else {
document.querySelectorAll("#source ." + category).forEach(e => e.classList.remove(cls));
btn.classList.remove(cls);
}
}
};
// Return the nth line div.
coverage.line_elt = function (n) {
return document.getElementById("t" + n)?.closest("p");
};
// Set the selection. b and e are line numbers.
coverage.set_sel = function (b, e) {
// The first line selected.
coverage.sel_begin = b;
// The next line not selected.
coverage.sel_end = (e === undefined) ? b+1 : e;
};
coverage.to_top = function () {
coverage.set_sel(0, 1);
coverage.scroll_window(0);
};
coverage.to_first_chunk = function () {
coverage.set_sel(0, 1);
coverage.to_next_chunk();
};
coverage.to_prev_file = function () {
window.location = document.getElementById("prevFileLink").href;
}
coverage.to_next_file = function () {
window.location = document.getElementById("nextFileLink").href;
}
coverage.to_index = function () {
location.href = document.getElementById("indexLink").href;
}
coverage.show_hide_help = function () {
const helpCheck = document.getElementById("help_panel_state")
helpCheck.checked = !helpCheck.checked;
}
// Return a string indicating what kind of chunk this line belongs to,
// or null if not a chunk.
coverage.chunk_indicator = function (line_elt) {
const classes = line_elt?.className;
if (!classes) {
return null;
}
const match = classes.match(/\bshow_\w+\b/);
if (!match) {
return null;
}
return match[0];
};
coverage.to_next_chunk = function () {
const c = coverage;
// Find the start of the next colored chunk.
var probe = c.sel_end;
var chunk_indicator, probe_line;
while (true) {
probe_line = c.line_elt(probe);
if (!probe_line) {
return;
}
chunk_indicator = c.chunk_indicator(probe_line);
if (chunk_indicator) {
break;
}
probe++;
}
// There's a next chunk, `probe` points to it.
var begin = probe;
// Find the end of this chunk.
var next_indicator = chunk_indicator;
while (next_indicator === chunk_indicator) {
probe++;
probe_line = c.line_elt(probe);
next_indicator = c.chunk_indicator(probe_line);
}
c.set_sel(begin, probe);
c.show_selection();
};
coverage.to_prev_chunk = function () {
const c = coverage;
// Find the end of the prev colored chunk.
var probe = c.sel_begin-1;
var probe_line = c.line_elt(probe);
if (!probe_line) {
return;
}
var chunk_indicator = c.chunk_indicator(probe_line);
while (probe > 1 && !chunk_indicator) {
probe--;
probe_line = c.line_elt(probe);
if (!probe_line) {
return;
}
chunk_indicator = c.chunk_indicator(probe_line);
}
// There's a prev chunk, `probe` points to its last line.
var end = probe+1;
// Find the beginning of this chunk.
var prev_indicator = chunk_indicator;
while (prev_indicator === chunk_indicator) {
probe--;
if (probe <= 0) {
return;
}
probe_line = c.line_elt(probe);
prev_indicator = c.chunk_indicator(probe_line);
}
c.set_sel(probe+1, end);
c.show_selection();
};
// Returns 0, 1, or 2: how many of the two ends of the selection are on
// the screen right now?
coverage.selection_ends_on_screen = function () {
if (coverage.sel_begin === 0) {
return 0;
}
const begin = coverage.line_elt(coverage.sel_begin);
const end = coverage.line_elt(coverage.sel_end-1);
return (
(checkVisible(begin) ? 1 : 0)
+ (checkVisible(end) ? 1 : 0)
);
};
coverage.to_next_chunk_nicely = function () {
if (coverage.selection_ends_on_screen() === 0) {
// The selection is entirely off the screen:
// Set the top line on the screen as selection.
// This will select the top-left of the viewport
// As this is most likely the span with the line number we take the parent
const line = document.elementFromPoint(0, 0).parentElement;
if (line.parentElement !== document.getElementById("source")) {
// The element is not a source line but the header or similar
coverage.select_line_or_chunk(1);
}
else {
// We extract the line number from the id
coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10));
}
}
coverage.to_next_chunk();
};
coverage.to_prev_chunk_nicely = function () {
if (coverage.selection_ends_on_screen() === 0) {
// The selection is entirely off the screen:
// Set the lowest line on the screen as selection.
// This will select the bottom-left of the viewport
// As this is most likely the span with the line number we take the parent
const line = document.elementFromPoint(document.documentElement.clientHeight-1, 0).parentElement;
if (line.parentElement !== document.getElementById("source")) {
// The element is not a source line but the header or similar
coverage.select_line_or_chunk(coverage.lines_len);
}
else {
// We extract the line number from the id
coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10));
}
}
coverage.to_prev_chunk();
};
// Select line number lineno, or if it is in a colored chunk, select the
// entire chunk
coverage.select_line_or_chunk = function (lineno) {
var c = coverage;
var probe_line = c.line_elt(lineno);
if (!probe_line) {
return;
}
var the_indicator = c.chunk_indicator(probe_line);
if (the_indicator) {
// The line is in a highlighted chunk.
// Search backward for the first line.
var probe = lineno;
var indicator = the_indicator;
while (probe > 0 && indicator === the_indicator) {
probe--;
probe_line = c.line_elt(probe);
if (!probe_line) {
break;
}
indicator = c.chunk_indicator(probe_line);
}
var begin = probe + 1;
// Search forward for the last line.
probe = lineno;
indicator = the_indicator;
while (indicator === the_indicator) {
probe++;
probe_line = c.line_elt(probe);
indicator = c.chunk_indicator(probe_line);
}
coverage.set_sel(begin, probe);
}
else {
coverage.set_sel(lineno);
}
};
coverage.show_selection = function () {
// Highlight the lines in the chunk
document.querySelectorAll("#source .highlight").forEach(e => e.classList.remove("highlight"));
for (let probe = coverage.sel_begin; probe < coverage.sel_end; probe++) {
coverage.line_elt(probe).querySelector(".n").classList.add("highlight");
}
coverage.scroll_to_selection();
};
coverage.scroll_to_selection = function () {
// Scroll the page if the chunk isn't fully visible.
if (coverage.selection_ends_on_screen() < 2) {
const element = coverage.line_elt(coverage.sel_begin);
coverage.scroll_window(element.offsetTop - 60);
}
};
coverage.scroll_window = function (to_pos) {
window.scroll({top: to_pos, behavior: "smooth"});
};
coverage.init_scroll_markers = function () {
// Init some variables
coverage.lines_len = document.querySelectorAll("#source > p").length;
// Build html
coverage.build_scroll_markers();
};
coverage.build_scroll_markers = function () {
const temp_scroll_marker = document.getElementById("scroll_marker")
if (temp_scroll_marker) temp_scroll_marker.remove();
// Don't build markers if the window has no scroll bar.
if (document.body.scrollHeight <= window.innerHeight) {
return;
}
const marker_scale = window.innerHeight / document.body.scrollHeight;
const line_height = Math.min(Math.max(3, window.innerHeight / coverage.lines_len), 10);
let previous_line = -99, last_mark, last_top;
const scroll_marker = document.createElement("div");
scroll_marker.id = "scroll_marker";
document.getElementById("source").querySelectorAll(
"p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par"
).forEach(element => {
const line_top = Math.floor(element.offsetTop * marker_scale);
const line_number = parseInt(element.querySelector(".n a").id.substr(1));
if (line_number === previous_line + 1) {
// If this solid missed block just make previous mark higher.
last_mark.style.height = `${line_top + line_height - last_top}px`;
}
else {
// Add colored line in scroll_marker block.
last_mark = document.createElement("div");
last_mark.id = `m${line_number}`;
last_mark.classList.add("marker");
last_mark.style.height = `${line_height}px`;
last_mark.style.top = `${line_top}px`;
scroll_marker.append(last_mark);
last_top = line_top;
}
previous_line = line_number;
});
// Append last to prevent layout calculation
document.body.append(scroll_marker);
};
coverage.wire_up_sticky_header = function () {
const header = document.querySelector("header");
const header_bottom = (
header.querySelector(".content h2").getBoundingClientRect().top -
header.getBoundingClientRect().top
);
function updateHeader() {
if (window.scrollY > header_bottom) {
header.classList.add("sticky");
}
else {
header.classList.remove("sticky");
}
}
window.addEventListener("scroll", updateHeader);
updateHeader();
};
coverage.expand_contexts = function (e) {
var ctxs = e.target.parentNode.querySelector(".ctxs");
if (!ctxs.classList.contains("expanded")) {
var ctxs_text = ctxs.textContent;
var width = Number(ctxs_text[0]);
ctxs.textContent = "";
for (var i = 1; i < ctxs_text.length; i += width) {
key = ctxs_text.substring(i, i + width).trim();
ctxs.appendChild(document.createTextNode(contexts[key]));
ctxs.appendChild(document.createElement("br"));
}
ctxs.classList.add("expanded");
}
};
document.addEventListener("DOMContentLoaded", () => {
if (document.body.classList.contains("indexfile")) {
coverage.index_ready();
}
else {
coverage.pyfile_ready();
}
});

BIN
htmlcov/favicon_32_cb_58284776.png View File

Before After
Width: 32  |  Height: 32  |  Size: 1.7 KiB

+ 1595
- 0
htmlcov/function_index.html
File diff suppressed because it is too large
View File


+ 608
- 0
htmlcov/index.html View File

@ -0,0 +1,608 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage report</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="indexfile">
<header>
<div class="content">
<h1>Coverage report:
<span class="pc_cov">93%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>f</kbd>
<kbd>s</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
<kbd>c</kbd>
&nbsp; change column sorting
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<form id="filter_container">
<input id="filter" type="text" value="" placeholder="filter...">
<div>
<input id="hide100" type="checkbox" >
<label for="hide100">hide covered</label>
</div>
</form>
<h2>
<a class="button current">Files</a>
<a class="button" href="function_index.html">Functions</a>
<a class="button" href="class_index.html">Classes</a>
</h2>
<p class="text">
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
</div>
</header>
<main id="index">
<table class="index" data-sortable>
<thead>
<tr class="tablehead" title="Click to sort">
<th id="file" class="name left" aria-sort="none" data-shortcut="f">File<span class="arrows"></span></th>
<th id="statements" aria-sort="none" data-default-sort-order="descending" data-shortcut="s">statements<span class="arrows"></span></th>
<th id="missing" aria-sort="none" data-default-sort-order="descending" data-shortcut="m">missing<span class="arrows"></span></th>
<th id="excluded" aria-sort="none" data-default-sort-order="descending" data-shortcut="x">excluded<span class="arrows"></span></th>
<th id="coverage" class="right" aria-sort="none" data-shortcut="c">coverage<span class="arrows"></span></th>
</tr>
</thead>
<tbody>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af___init___py.html">Community/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_admin_py.html">Community/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_apps_py.html">Community/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1267b767d4b92e81_0001_initial_py.html">Community/migrations/0001_initial.py</a></td>
<td>5</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="5 5">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1267b767d4b92e81_0002_initial_py.html">Community/migrations/0002_initial.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1267b767d4b92e81___init___py.html">Community/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_models_py.html">Community/models.py</a></td>
<td>27</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="27 27">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_tests_py.html">Community/tests.py</a></td>
<td>105</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="105 105">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_urls_py.html">Community/urls.py</a></td>
<td>6</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="6 6">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f952cfc16e2397af_views_py.html">Community/views.py</a></td>
<td>97</td>
<td>13</td>
<td>0</td>
<td class="right" data-ratio="84 97">87%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0___init___py.html">Home/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_admin_py.html">Home/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_apps_py.html">Home/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_12dff67f314accae___init___py.html">Home/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_models_py.html">Home/models.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_tests_py.html">Home/tests.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_urls_py.html">Home/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_4f885700d30561f0_views_py.html">Home/views.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f___init___py.html">LifeServing/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_admin_py.html">LifeServing/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_apps_py.html">LifeServing/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_d41ba54ead348612___init___py.html">LifeServing/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_models_py.html">LifeServing/models.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_tests_py.html">LifeServing/tests.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_urls_py.html">LifeServing/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_bf33ad1e1d674c9f_views_py.html">LifeServing/views.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1___init___py.html">MyPage/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_admin_py.html">MyPage/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_apps_py.html">MyPage/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_forms_py.html">MyPage/forms.py</a></td>
<td>12</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="12 12">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_de2a206739ffda05_0001_initial_py.html">MyPage/migrations/0001_initial.py</a></td>
<td>5</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="5 5">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_de2a206739ffda05_0002_initial_py.html">MyPage/migrations/0002_initial.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_de2a206739ffda05___init___py.html">MyPage/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_models_py.html">MyPage/models.py</a></td>
<td>21</td>
<td>2</td>
<td>0</td>
<td class="right" data-ratio="19 21">90%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_tests_py.html">MyPage/tests.py</a></td>
<td>95</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="95 95">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_urls_py.html">MyPage/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_e21dcdf47756d8f1_views_py.html">MyPage/views.py</a></td>
<td>74</td>
<td>17</td>
<td>0</td>
<td class="right" data-ratio="57 74">77%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209___init___py.html">SLClassroom/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_admin_py.html">SLClassroom/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_apps_py.html">SLClassroom/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_3d86ff49411af6eb___init___py.html">SLClassroom/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_models_py.html">SLClassroom/models.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_tests_py.html">SLClassroom/tests.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_urls_py.html">SLClassroom/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_62036e58f7454209_views_py.html">SLClassroom/views.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293___init___py.html">Schedule/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_admin_py.html">Schedule/admin.py</a></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="1 1">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_apps_py.html">Schedule/apps.py</a></td>
<td>4</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="4 4">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1778eb5d946b9af5_0001_initial_py.html">Schedule/migrations/0001_initial.py</a></td>
<td>5</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="5 5">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1778eb5d946b9af5_0002_initial_py.html">Schedule/migrations/0002_initial.py</a></td>
<td>7</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="7 7">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_1778eb5d946b9af5___init___py.html">Schedule/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_models_py.html">Schedule/models.py</a></td>
<td>20</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="20 20">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_serializers_py.html">Schedule/serializers.py</a></td>
<td>11</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="11 11">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_tests_py.html">Schedule/tests.py</a></td>
<td>52</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="52 52">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_urls_py.html">Schedule/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_5c71e8f1e4812293_views_py.html">Schedule/views.py</a></td>
<td>67</td>
<td>22</td>
<td>0</td>
<td class="right" data-ratio="45 67">67%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_c450d40fba27812a___init___py.html">WaveSign/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_c450d40fba27812a_settings_py.html">WaveSign/settings.py</a></td>
<td>26</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="26 26">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_c450d40fba27812a_urls_py.html">WaveSign/urls.py</a></td>
<td>9</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="9 9">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_c450d40fba27812a_views_py.html">WaveSign/views.py</a></td>
<td>7</td>
<td>3</td>
<td>0</td>
<td class="right" data-ratio="4 7">57%</td>
</tr>
<tr class="region">
<td class="name left"><a href="manage_py.html">manage.py</a></td>
<td>11</td>
<td>2</td>
<td>0</td>
<td class="right" data-ratio="9 11">82%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e___init___py.html">users/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_admin_py.html">users/admin.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_apps_py.html">users/apps.py</a></td>
<td>6</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="6 6">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_forms_py.html">users/forms.py</a></td>
<td>40</td>
<td>1</td>
<td>0</td>
<td class="right" data-ratio="39 40">98%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_d7caba16f2a88201_0001_initial_py.html">users/migrations/0001_initial.py</a></td>
<td>8</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="8 8">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_d7caba16f2a88201___init___py.html">users/migrations/__init__.py</a></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="0 0">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_models_py.html">users/models.py</a></td>
<td>12</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="12 12">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_signals_py.html">users/signals.py</a></td>
<td>8</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="8 8">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_tests_py.html">users/tests.py</a></td>
<td>40</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="40 40">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_urls_py.html">users/urls.py</a></td>
<td>3</td>
<td>0</td>
<td>0</td>
<td class="right" data-ratio="3 3">100%</td>
</tr>
<tr class="region">
<td class="name left"><a href="z_f6c68bdc9becfc1e_views_py.html">users/views.py</a></td>
<td>42</td>
<td>4</td>
<td>0</td>
<td class="right" data-ratio="38 42">90%</td>
</tr>
</tbody>
<tfoot>
<tr class="total">
<td class="name left">Total</td>
<td>916</td>
<td>64</td>
<td>0</td>
<td class="right" data-ratio="852 916">93%</td>
</tr>
</tfoot>
</table>
<p id="no_rows">
No items found using the specified filter.
</p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
</div>
<aside class="hidden">
<a id="prevFileLink" class="nav" href="z_f6c68bdc9becfc1e_views_py.html"></a>
<a id="nextFileLink" class="nav" href="z_f952cfc16e2397af___init___py.html"></a>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</footer>
</body>
</html>

BIN
htmlcov/keybd_closed_cb_ce680311.png View File

Before After
Width: 21  |  Height: 12  |  Size: 8.8 KiB

+ 119
- 0
htmlcov/manage_py.html View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for manage.py: 82%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>manage.py</b>:
<span class="pc_cov">82%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">11 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">9<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">2<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_c450d40fba27812a_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_f6c68bdc9becfc1e___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com">#!/usr/bin/env python</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="str">"""Django's command-line utility for administrative tasks."""</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">import</span> <span class="nam">os</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">import</span> <span class="nam">sys</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"><span class="key">def</span> <span class="nam">main</span><span class="op">(</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="str">"""Run administrative tasks."""</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"> <span class="nam">os</span><span class="op">.</span><span class="nam">environ</span><span class="op">.</span><span class="nam">setdefault</span><span class="op">(</span><span class="str">"DJANGO_SETTINGS_MODULE"</span><span class="op">,</span> <span class="str">"WaveSign.settings"</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="key">try</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">core</span><span class="op">.</span><span class="nam">management</span> <span class="key">import</span> <span class="nam">execute_from_command_line</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="key">except</span> <span class="nam">ImportError</span> <span class="key">as</span> <span class="nam">exc</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="key">raise</span> <span class="nam">ImportError</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="str">"Couldn't import Django. Are you sure it's installed and "</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="str">"available on your PYTHONPATH environment variable? Did you "</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="str">"forget to activate a virtual environment?"</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="op">)</span> <span class="key">from</span> <span class="nam">exc</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">execute_from_command_line</span><span class="op">(</span><span class="nam">sys</span><span class="op">.</span><span class="nam">argv</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"><span class="key">if</span> <span class="nam">__name__</span> <span class="op">==</span> <span class="str">"__main__"</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">main</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_c450d40fba27812a_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_f6c68bdc9becfc1e___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 1
- 0
htmlcov/status.json
File diff suppressed because it is too large
View File


+ 337
- 0
htmlcov/style_cb_8e611ae1.css View File

@ -0,0 +1,337 @@
@charset "UTF-8";
/* Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 */
/* For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt */
/* Don't edit this .css file. Edit the .scss file instead! */
html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 1em; background: #fff; color: #000; }
@media (prefers-color-scheme: dark) { body { background: #1e1e1e; } }
@media (prefers-color-scheme: dark) { body { color: #eee; } }
html > body { font-size: 16px; }
a:active, a:focus { outline: 2px dashed #007acc; }
p { font-size: .875em; line-height: 1.4em; }
table { border-collapse: collapse; }
td { vertical-align: top; }
table tr.hidden { display: none !important; }
p#no_rows { display: none; font-size: 1.15em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
a.nav { text-decoration: none; color: inherit; }
a.nav:hover { text-decoration: underline; color: inherit; }
.hidden { display: none; }
header { background: #f8f8f8; width: 100%; z-index: 2; border-bottom: 1px solid #ccc; }
@media (prefers-color-scheme: dark) { header { background: black; } }
@media (prefers-color-scheme: dark) { header { border-color: #333; } }
header .content { padding: 1rem 3.5rem; }
header h2 { margin-top: .5em; font-size: 1em; }
header h2 a.button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; }
@media (prefers-color-scheme: dark) { header h2 a.button { background: #333; } }
@media (prefers-color-scheme: dark) { header h2 a.button { border-color: #444; } }
header h2 a.button.current { border: 2px solid; background: #fff; border-color: #999; cursor: default; }
@media (prefers-color-scheme: dark) { header h2 a.button.current { background: #1e1e1e; } }
@media (prefers-color-scheme: dark) { header h2 a.button.current { border-color: #777; } }
header p.text { margin: .5em 0 -.5em; color: #666; font-style: italic; }
@media (prefers-color-scheme: dark) { header p.text { color: #aaa; } }
header.sticky { position: fixed; left: 0; right: 0; height: 2.5em; }
header.sticky .text { display: none; }
header.sticky h1, header.sticky h2 { font-size: 1em; margin-top: 0; display: inline-block; }
header.sticky .content { padding: 0.5rem 3.5rem; }
header.sticky .content p { font-size: 1em; }
header.sticky ~ #source { padding-top: 6.5em; }
main { position: relative; z-index: 1; }
footer { margin: 1rem 3.5rem; }
footer .content { padding: 0; color: #666; font-style: italic; }
@media (prefers-color-scheme: dark) { footer .content { color: #aaa; } }
#index { margin: 1rem 0 0 3.5rem; }
h1 { font-size: 1.25em; display: inline-block; }
#filter_container { float: right; margin: 0 2em 0 0; line-height: 1.66em; }
#filter_container #filter { width: 10em; padding: 0.2em 0.5em; border: 2px solid #ccc; background: #fff; color: #000; }
@media (prefers-color-scheme: dark) { #filter_container #filter { border-color: #444; } }
@media (prefers-color-scheme: dark) { #filter_container #filter { background: #1e1e1e; } }
@media (prefers-color-scheme: dark) { #filter_container #filter { color: #eee; } }
#filter_container #filter:focus { border-color: #007acc; }
#filter_container :disabled ~ label { color: #ccc; }
@media (prefers-color-scheme: dark) { #filter_container :disabled ~ label { color: #444; } }
#filter_container label { font-size: .875em; color: #666; }
@media (prefers-color-scheme: dark) { #filter_container label { color: #aaa; } }
header button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; }
@media (prefers-color-scheme: dark) { header button { background: #333; } }
@media (prefers-color-scheme: dark) { header button { border-color: #444; } }
header button:active, header button:focus { outline: 2px dashed #007acc; }
header button.run { background: #eeffee; }
@media (prefers-color-scheme: dark) { header button.run { background: #373d29; } }
header button.run.show_run { background: #dfd; border: 2px solid #00dd00; margin: 0 .1em; }
@media (prefers-color-scheme: dark) { header button.run.show_run { background: #373d29; } }
header button.mis { background: #ffeeee; }
@media (prefers-color-scheme: dark) { header button.mis { background: #4b1818; } }
header button.mis.show_mis { background: #fdd; border: 2px solid #ff0000; margin: 0 .1em; }
@media (prefers-color-scheme: dark) { header button.mis.show_mis { background: #4b1818; } }
header button.exc { background: #f7f7f7; }
@media (prefers-color-scheme: dark) { header button.exc { background: #333; } }
header button.exc.show_exc { background: #eee; border: 2px solid #808080; margin: 0 .1em; }
@media (prefers-color-scheme: dark) { header button.exc.show_exc { background: #333; } }
header button.par { background: #ffffd5; }
@media (prefers-color-scheme: dark) { header button.par { background: #650; } }
header button.par.show_par { background: #ffa; border: 2px solid #bbbb00; margin: 0 .1em; }
@media (prefers-color-scheme: dark) { header button.par.show_par { background: #650; } }
#help_panel, #source p .annotate.long { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; color: #333; padding: .25em .5em; }
#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; }
#help_panel_wrapper { float: right; position: relative; }
#keyboard_icon { margin: 5px; }
#help_panel_state { display: none; }
#help_panel { top: 25px; right: 0; padding: .75em; border: 1px solid #883; color: #333; }
#help_panel .keyhelp p { margin-top: .75em; }
#help_panel .legend { font-style: italic; margin-bottom: 1em; }
.indexfile #help_panel { width: 25em; }
.pyfile #help_panel { width: 18em; }
#help_panel_state:checked ~ #help_panel { display: block; }
kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-weight: bold; background: #eee; border-radius: 3px; }
#source { padding: 1em 0 1em 3.5rem; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
#source p { position: relative; white-space: pre; }
#source p * { box-sizing: border-box; }
#source p .n { float: left; text-align: right; width: 3.5rem; box-sizing: border-box; margin-left: -3.5rem; padding-right: 1em; color: #999; user-select: none; }
@media (prefers-color-scheme: dark) { #source p .n { color: #777; } }
#source p .n.highlight { background: #ffdd00; }
#source p .n a { scroll-margin-top: 6em; text-decoration: none; color: #999; }
@media (prefers-color-scheme: dark) { #source p .n a { color: #777; } }
#source p .n a:hover { text-decoration: underline; color: #999; }
@media (prefers-color-scheme: dark) { #source p .n a:hover { color: #777; } }
#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid #fff; }
@media (prefers-color-scheme: dark) { #source p .t { border-color: #1e1e1e; } }
#source p .t:hover { background: #f2f2f2; }
@media (prefers-color-scheme: dark) { #source p .t:hover { background: #282828; } }
#source p .t:hover ~ .r .annotate.long { display: block; }
#source p .t .com { color: #008000; font-style: italic; line-height: 1px; }
@media (prefers-color-scheme: dark) { #source p .t .com { color: #6a9955; } }
#source p .t .key { font-weight: bold; line-height: 1px; }
#source p .t .str { color: #0451a5; }
@media (prefers-color-scheme: dark) { #source p .t .str { color: #9cdcfe; } }
#source p.mis .t { border-left: 0.2em solid #ff0000; }
#source p.mis.show_mis .t { background: #fdd; }
@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t { background: #4b1818; } }
#source p.mis.show_mis .t:hover { background: #f2d2d2; }
@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } }
#source p.run .t { border-left: 0.2em solid #00dd00; }
#source p.run.show_run .t { background: #dfd; }
@media (prefers-color-scheme: dark) { #source p.run.show_run .t { background: #373d29; } }
#source p.run.show_run .t:hover { background: #d2f2d2; }
@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } }
#source p.exc .t { border-left: 0.2em solid #808080; }
#source p.exc.show_exc .t { background: #eee; }
@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t { background: #333; } }
#source p.exc.show_exc .t:hover { background: #e2e2e2; }
@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } }
#source p.par .t { border-left: 0.2em solid #bbbb00; }
#source p.par.show_par .t { background: #ffa; }
@media (prefers-color-scheme: dark) { #source p.par.show_par .t { background: #650; } }
#source p.par.show_par .t:hover { background: #f2f2a2; }
@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } }
#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; }
@media (prefers-color-scheme: dark) { #source p .annotate { color: #ddd; } }
#source p .annotate.short:hover ~ .long { display: block; }
#source p .annotate.long { width: 30em; right: 2.5em; }
#source p input { display: none; }
#source p input ~ .r label.ctx { cursor: pointer; border-radius: .25em; }
#source p input ~ .r label.ctx::before { content: "▶ "; }
#source p input ~ .r label.ctx:hover { background: #e8f4ff; color: #666; }
@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { background: #0f3a42; } }
@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { color: #aaa; } }
#source p input:checked ~ .r label.ctx { background: #d0e8ff; color: #666; border-radius: .75em .75em 0 0; padding: 0 .5em; margin: -.25em 0; }
@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { background: #056; } }
@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { color: #aaa; } }
#source p input:checked ~ .r label.ctx::before { content: "▼ "; }
#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; }
#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; }
@media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } }
#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; text-align: right; }
@media (prefers-color-scheme: dark) { #source p .ctxs { background: #056; } }
#index { font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875em; }
#index table.index { margin-left: -.5em; }
#index td, #index th { text-align: right; padding: .25em .5em; border-bottom: 1px solid #eee; }
@media (prefers-color-scheme: dark) { #index td, #index th { border-color: #333; } }
#index td.name, #index th.name { text-align: left; width: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; min-width: 15em; }
#index th { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-style: italic; color: #333; cursor: pointer; }
@media (prefers-color-scheme: dark) { #index th { color: #ddd; } }
#index th:hover { background: #eee; }
@media (prefers-color-scheme: dark) { #index th:hover { background: #333; } }
#index th .arrows { color: #666; font-size: 85%; font-family: sans-serif; font-style: normal; pointer-events: none; }
#index th[aria-sort="ascending"], #index th[aria-sort="descending"] { white-space: nowrap; background: #eee; padding-left: .5em; }
@media (prefers-color-scheme: dark) { #index th[aria-sort="ascending"], #index th[aria-sort="descending"] { background: #333; } }
#index th[aria-sort="ascending"] .arrows::after { content: " ▲"; }
#index th[aria-sort="descending"] .arrows::after { content: " ▼"; }
#index td.name { font-size: 1.15em; }
#index td.name a { text-decoration: none; color: inherit; }
#index td.name .no-noun { font-style: italic; }
#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; }
#index tr.region:hover { background: #eee; }
@media (prefers-color-scheme: dark) { #index tr.region:hover { background: #333; } }
#index tr.region:hover td.name { text-decoration: underline; color: inherit; }
#scroll_marker { position: fixed; z-index: 3; right: 0; top: 0; width: 16px; height: 100%; background: #fff; border-left: 1px solid #eee; will-change: transform; }
@media (prefers-color-scheme: dark) { #scroll_marker { background: #1e1e1e; } }
@media (prefers-color-scheme: dark) { #scroll_marker { border-color: #333; } }
#scroll_marker .marker { background: #ccc; position: absolute; min-height: 3px; width: 100%; }
@media (prefers-color-scheme: dark) { #scroll_marker .marker { background: #444; } }

+ 183
- 0
htmlcov/z_1267b767d4b92e81_0001_initial_py.html View File

@ -0,0 +1,183 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Community/migrations/0001_initial.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Community/migrations/0001_initial.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">5 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">5<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_f952cfc16e2397af_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_1267b767d4b92e81_0002_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># Generated by Django 5.2 on 2025-05-30 01:17</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">migrations</span><span class="op">,</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="key">class</span> <span class="nam">Migration</span><span class="op">(</span><span class="nam">migrations</span><span class="op">.</span><span class="nam">Migration</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="nam">initial</span> <span class="op">=</span> <span class="key">True</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">dependencies</span> <span class="op">=</span> <span class="op">[</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">operations</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Comment"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="op">(</span><span class="str">"content"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TextField</span><span class="op">(</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Favorite"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Like"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t48" href="#t48">48</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t49" href="#t49">49</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t50" href="#t50">50</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t51" href="#t51">51</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t52" href="#t52">52</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t53" href="#t53">53</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t54" href="#t54">54</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t55" href="#t55">55</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t56" href="#t56">56</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t57" href="#t57">57</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t58" href="#t58">58</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t59" href="#t59">59</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t60" href="#t60">60</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Post"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t61" href="#t61">61</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t62" href="#t62">62</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t63" href="#t63">63</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t64" href="#t64">64</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t65" href="#t65">65</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t66" href="#t66">66</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t67" href="#t67">67</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t68" href="#t68">68</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t69" href="#t69">69</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t70" href="#t70">70</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t71" href="#t71">71</a></span><span class="t"> <span class="op">(</span><span class="str">"content"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TextField</span><span class="op">(</span><span class="nam">verbose_name</span><span class="op">=</span><span class="str">"&#20869;&#23481;"</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t72" href="#t72">72</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t73" href="#t73">73</a></span><span class="t"> <span class="str">"image"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t74" href="#t74">74</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">ImageField</span><span class="op">(</span><span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">upload_to</span><span class="op">=</span><span class="str">"post_images/"</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t75" href="#t75">75</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t76" href="#t76">76</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t77" href="#t77">77</a></span><span class="t"> <span class="str">"video"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t78" href="#t78">78</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">FileField</span><span class="op">(</span><span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">upload_to</span><span class="op">=</span><span class="str">"post_videos/"</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t79" href="#t79">79</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t80" href="#t80">80</a></span><span class="t"> <span class="op">(</span><span class="str">"like_count"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">PositiveIntegerField</span><span class="op">(</span><span class="nam">default</span><span class="op">=</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t81" href="#t81">81</a></span><span class="t"> <span class="op">(</span><span class="str">"comment_count"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">PositiveIntegerField</span><span class="op">(</span><span class="nam">default</span><span class="op">=</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t82" href="#t82">82</a></span><span class="t"> <span class="op">(</span><span class="str">"favorite_count"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">PositiveIntegerField</span><span class="op">(</span><span class="nam">default</span><span class="op">=</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t83" href="#t83">83</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t84" href="#t84">84</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t85" href="#t85">85</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t86" href="#t86">86</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_f952cfc16e2397af_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_1267b767d4b92e81_0002_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 164
- 0
htmlcov/z_1267b767d4b92e81_0002_initial_py.html View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Community/migrations/0002_initial.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Community/migrations/0002_initial.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">7 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">7<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_1267b767d4b92e81_0001_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_1267b767d4b92e81___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># Generated by Django 5.2 on 2025-05-30 01:17</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">import</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">conf</span> <span class="key">import</span> <span class="nam">settings</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">migrations</span><span class="op">,</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"><span class="key">class</span> <span class="nam">Migration</span><span class="op">(</span><span class="nam">migrations</span><span class="op">.</span><span class="nam">Migration</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">initial</span> <span class="op">=</span> <span class="key">True</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">dependencies</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="op">(</span><span class="str">"Community"</span><span class="op">,</span> <span class="str">"0001_initial"</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">swappable_dependency</span><span class="op">(</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="nam">operations</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"comment"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"favorite"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"like"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"post"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"like"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t48" href="#t48">48</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"post"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t49" href="#t49">49</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t50" href="#t50">50</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="str">"Community.post"</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t51" href="#t51">51</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t52" href="#t52">52</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t53" href="#t53">53</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t54" href="#t54">54</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"favorite"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t55" href="#t55">55</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"post"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t56" href="#t56">56</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t57" href="#t57">57</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="str">"Community.post"</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t58" href="#t58">58</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t59" href="#t59">59</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t60" href="#t60">60</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t61" href="#t61">61</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"comment"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t62" href="#t62">62</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"post"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t63" href="#t63">63</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t64" href="#t64">64</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">to</span><span class="op">=</span><span class="str">"Community.post"</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t65" href="#t65">65</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t66" href="#t66">66</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t67" href="#t67">67</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_1267b767d4b92e81_0001_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_1267b767d4b92e81___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_1267b767d4b92e81___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Community/migrations/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Community/migrations/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_1267b767d4b92e81_0002_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_f952cfc16e2397af_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_1267b767d4b92e81_0002_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_f952cfc16e2397af_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_12dff67f314accae___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/migrations/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/migrations/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 146
- 0
htmlcov/z_1778eb5d946b9af5_0001_initial_py.html View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/migrations/0001_initial.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/migrations/0001_initial.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">5 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">5<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_1778eb5d946b9af5_0002_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># Generated by Django 5.2 on 2025-05-30 01:17</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">migrations</span><span class="op">,</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="key">class</span> <span class="nam">Migration</span><span class="op">(</span><span class="nam">migrations</span><span class="op">.</span><span class="nam">Migration</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="nam">initial</span> <span class="op">=</span> <span class="key">True</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">dependencies</span> <span class="op">=</span> <span class="op">[</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">operations</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Event"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="op">(</span><span class="str">"title"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">CharField</span><span class="op">(</span><span class="nam">max_length</span><span class="op">=</span><span class="num">200</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="op">(</span><span class="str">"date"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateField</span><span class="op">(</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t"> <span class="op">(</span><span class="str">"time"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TimeField</span><span class="op">(</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="op">(</span><span class="str">"description"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TextField</span><span class="op">(</span><span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">CreateModel</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"Task"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"> <span class="nam">fields</span><span class="op">=</span><span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t"> <span class="str">"id"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"> <span class="nam">models</span><span class="op">.</span><span class="nam">BigAutoField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t"> <span class="nam">auto_created</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="nam">primary_key</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="nam">serialize</span><span class="op">=</span><span class="key">False</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t"> <span class="nam">verbose_name</span><span class="op">=</span><span class="str">"ID"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t"> <span class="op">(</span><span class="str">"text"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">CharField</span><span class="op">(</span><span class="nam">max_length</span><span class="op">=</span><span class="num">200</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t"> <span class="op">(</span><span class="str">"completed"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">BooleanField</span><span class="op">(</span><span class="nam">default</span><span class="op">=</span><span class="key">False</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="op">(</span><span class="str">"created_at"</span><span class="op">,</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="op">]</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t48" href="#t48">48</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t49" href="#t49">49</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_1778eb5d946b9af5_0002_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 144
- 0
htmlcov/z_1778eb5d946b9af5_0002_initial_py.html View File

@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/migrations/0002_initial.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/migrations/0002_initial.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">7 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">7<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_1778eb5d946b9af5_0001_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_1778eb5d946b9af5___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># Generated by Django 5.2 on 2025-05-30 01:17</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">import</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">conf</span> <span class="key">import</span> <span class="nam">settings</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">migrations</span><span class="op">,</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"><span class="key">class</span> <span class="nam">Migration</span><span class="op">(</span><span class="nam">migrations</span><span class="op">.</span><span class="nam">Migration</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">initial</span> <span class="op">=</span> <span class="key">True</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">dependencies</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="op">(</span><span class="str">"Schedule"</span><span class="op">,</span> <span class="str">"0001_initial"</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">swappable_dependency</span><span class="op">(</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="nam">operations</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"event"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t"> <span class="nam">related_name</span><span class="op">=</span><span class="str">"events"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"task"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"event"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t"> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">SET_NULL</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"> <span class="nam">related_name</span><span class="op">=</span><span class="str">"tasks"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="nam">to</span><span class="op">=</span><span class="str">"Schedule.event"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t"> <span class="nam">migrations</span><span class="op">.</span><span class="nam">AddField</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="nam">model_name</span><span class="op">=</span><span class="str">"task"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="nam">name</span><span class="op">=</span><span class="str">"user"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t"> <span class="nam">field</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">django</span><span class="op">.</span><span class="nam">db</span><span class="op">.</span><span class="nam">models</span><span class="op">.</span><span class="nam">deletion</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="nam">related_name</span><span class="op">=</span><span class="str">"tasks"</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t"> <span class="nam">to</span><span class="op">=</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_1778eb5d946b9af5_0001_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_1778eb5d946b9af5___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_1778eb5d946b9af5___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/migrations/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/migrations/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_1778eb5d946b9af5_0002_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_1778eb5d946b9af5_0002_initial_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_3d86ff49411af6eb___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for SLClassroom/migrations/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>SLClassroom/migrations/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_62036e58f7454209_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_62036e58f7454209_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_62036e58f7454209_apps_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_62036e58f7454209_models_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_4f885700d30561f0___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_f952cfc16e2397af_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_admin_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_f952cfc16e2397af_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_admin_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 100
- 0
htmlcov/z_4f885700d30561f0_admin_py.html View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/admin.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/admin.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">1 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">1<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_apps_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">contrib</span> <span class="key">import</span> <span class="nam">admin</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="com"># Register your models here.</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_apps_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 103
- 0
htmlcov/z_4f885700d30561f0_apps_py.html View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/apps.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/apps.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">4 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">4<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0_admin_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_12dff67f314accae___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">apps</span> <span class="key">import</span> <span class="nam">AppConfig</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">class</span> <span class="nam">HomeConfig</span><span class="op">(</span><span class="nam">AppConfig</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">default_auto_field</span> <span class="op">=</span> <span class="str">"django.db.models.BigAutoField"</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="nam">name</span> <span class="op">=</span> <span class="str">"Home"</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0_admin_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_12dff67f314accae___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 100
- 0
htmlcov/z_4f885700d30561f0_models_py.html View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/models.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/models.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">1 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">1<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_12dff67f314accae___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_tests_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="com"># Create your models here.</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_12dff67f314accae___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_tests_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 107
- 0
htmlcov/z_4f885700d30561f0_tests_py.html View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/tests.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/tests.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">7 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">7<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0_models_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_urls_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 18:55 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">test</span> <span class="key">import</span> <span class="nam">TestCase</span><span class="op">,</span> <span class="nam">Client</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">urls</span> <span class="key">import</span> <span class="nam">reverse</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="com"># Create your tests here.</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="key">class</span> <span class="nam">HomeViewTest</span><span class="op">(</span><span class="nam">TestCase</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_home_page</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="nam">client</span> <span class="op">=</span> <span class="nam">Client</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">client</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'home'</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">200</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0_models_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_urls_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 18:55 +0800
</p>
</div>
</footer>
</body>
</html>

+ 103
- 0
htmlcov/z_4f885700d30561f0_urls_py.html View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/urls.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/urls.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">3 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">3<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0_tests_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_4f885700d30561f0_views_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">urls</span> <span class="key">import</span> <span class="nam">path</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="op">.</span> <span class="key">import</span> <span class="nam">views</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="nam">urlpatterns</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">''</span><span class="op">,</span> <span class="nam">views</span><span class="op">.</span><span class="nam">index</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'home'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0_tests_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_4f885700d30561f0_views_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 102
- 0
htmlcov/z_4f885700d30561f0_views_py.html View File

@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Home/views.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Home/views.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">3 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">3<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_4f885700d30561f0_urls_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_bf33ad1e1d674c9f___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">shortcuts</span> <span class="key">import</span> <span class="nam">render</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="com"># Create your views here.</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">def</span> <span class="nam">index</span><span class="op">(</span><span class="nam">request</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="key">return</span> <span class="nam">render</span><span class="op">(</span><span class="nam">request</span><span class="op">,</span> <span class="str">'home.html'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_4f885700d30561f0_urls_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_bf33ad1e1d674c9f___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 97
- 0
htmlcov/z_5c71e8f1e4812293___init___py.html View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/__init__.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/__init__.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">0 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">0<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_62036e58f7454209_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_admin_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_62036e58f7454209_views_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_admin_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 100
- 0
htmlcov/z_5c71e8f1e4812293_admin_py.html View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/admin.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/admin.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">1 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">1<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_apps_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">contrib</span> <span class="key">import</span> <span class="nam">admin</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="com"># Register your models here.</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_apps_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 103
- 0
htmlcov/z_5c71e8f1e4812293_apps_py.html View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/apps.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/apps.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">4 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">4<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_admin_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_1778eb5d946b9af5_0001_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">apps</span> <span class="key">import</span> <span class="nam">AppConfig</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">class</span> <span class="nam">ScheduleConfig</span><span class="op">(</span><span class="nam">AppConfig</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">default_auto_field</span> <span class="op">=</span> <span class="str">"django.db.models.BigAutoField"</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="nam">name</span> <span class="op">=</span> <span class="str">"Schedule"</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_admin_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_1778eb5d946b9af5_0001_initial_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 123
- 0
htmlcov/z_5c71e8f1e4812293_models_py.html View File

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/models.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/models.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">20 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">20<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_1778eb5d946b9af5___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_serializers_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># schedule/models.py</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">db</span> <span class="key">import</span> <span class="nam">models</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">contrib</span><span class="op">.</span><span class="nam">auth</span><span class="op">.</span><span class="nam">models</span> <span class="key">import</span> <span class="nam">User</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">from</span> <span class="nam">WaveSign</span> <span class="key">import</span> <span class="nam">settings</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"><span class="key">class</span> <span class="nam">Event</span><span class="op">(</span><span class="nam">models</span><span class="op">.</span><span class="nam">Model</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="nam">user</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">,</span> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">related_name</span><span class="op">=</span><span class="str">'events'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"> <span class="nam">title</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">CharField</span><span class="op">(</span><span class="nam">max_length</span><span class="op">=</span><span class="num">200</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">date</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateField</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="nam">time</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TimeField</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">description</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">TextField</span><span class="op">(</span><span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="nam">created_at</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="key">def</span> <span class="nam">__str__</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="key">return</span> <span class="nam">self</span><span class="op">.</span><span class="nam">title</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"><span class="key">class</span> <span class="nam">Task</span><span class="op">(</span><span class="nam">models</span><span class="op">.</span><span class="nam">Model</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">user</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span><span class="nam">settings</span><span class="op">.</span><span class="nam">AUTH_USER_MODEL</span><span class="op">,</span> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">CASCADE</span><span class="op">,</span> <span class="nam">related_name</span><span class="op">=</span><span class="str">'tasks'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">text</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">CharField</span><span class="op">(</span><span class="nam">max_length</span><span class="op">=</span><span class="num">200</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">completed</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">BooleanField</span><span class="op">(</span><span class="nam">default</span><span class="op">=</span><span class="key">False</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">created_at</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">DateTimeField</span><span class="op">(</span><span class="nam">auto_now_add</span><span class="op">=</span><span class="key">True</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t"> <span class="nam">event</span> <span class="op">=</span> <span class="nam">models</span><span class="op">.</span><span class="nam">ForeignKey</span><span class="op">(</span><span class="nam">Event</span><span class="op">,</span> <span class="nam">on_delete</span><span class="op">=</span><span class="nam">models</span><span class="op">.</span><span class="nam">SET_NULL</span><span class="op">,</span> <span class="nam">blank</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">null</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">related_name</span><span class="op">=</span><span class="str">'tasks'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="key">def</span> <span class="nam">__str__</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="key">return</span> <span class="nam">self</span><span class="op">.</span><span class="nam">text</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_1778eb5d946b9af5___init___py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_serializers_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 112
- 0
htmlcov/z_5c71e8f1e4812293_serializers_py.html View File

@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/serializers.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/serializers.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">11 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">11<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_models_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_tests_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># schedule/serializers.py</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span> <span class="key">import</span> <span class="nam">serializers</span> <span class="com"># type: ignore</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="op">.</span><span class="nam">models</span> <span class="key">import</span> <span class="nam">Event</span><span class="op">,</span> <span class="nam">Task</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">class</span> <span class="nam">TaskSerializer</span><span class="op">(</span><span class="nam">serializers</span><span class="op">.</span><span class="nam">ModelSerializer</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="key">class</span> <span class="nam">Meta</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"> <span class="nam">model</span> <span class="op">=</span> <span class="nam">Task</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"> <span class="nam">fields</span> <span class="op">=</span> <span class="op">[</span><span class="str">'id'</span><span class="op">,</span> <span class="str">'text'</span><span class="op">,</span> <span class="str">'completed'</span><span class="op">,</span> <span class="str">'created_at'</span><span class="op">,</span> <span class="str">'event'</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"><span class="key">class</span> <span class="nam">EventSerializer</span><span class="op">(</span><span class="nam">serializers</span><span class="op">.</span><span class="nam">ModelSerializer</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="nam">tasks</span> <span class="op">=</span> <span class="nam">TaskSerializer</span><span class="op">(</span><span class="nam">many</span><span class="op">=</span><span class="key">True</span><span class="op">,</span> <span class="nam">read_only</span><span class="op">=</span><span class="key">True</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="key">class</span> <span class="nam">Meta</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">model</span> <span class="op">=</span> <span class="nam">Event</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">fields</span> <span class="op">=</span> <span class="op">[</span><span class="str">'id'</span><span class="op">,</span> <span class="str">'title'</span><span class="op">,</span> <span class="str">'date'</span><span class="op">,</span> <span class="str">'time'</span><span class="op">,</span> <span class="str">'description'</span><span class="op">,</span> <span class="str">'created_at'</span><span class="op">,</span> <span class="str">'tasks'</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_models_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_tests_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 162
- 0
htmlcov/z_5c71e8f1e4812293_tests_py.html View File

@ -0,0 +1,162 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/tests.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/tests.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">52 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">52<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_serializers_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_urls_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">test</span> <span class="key">import</span> <span class="nam">TestCase</span><span class="op">,</span> <span class="nam">Client</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">urls</span> <span class="key">import</span> <span class="nam">reverse</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">contrib</span><span class="op">.</span><span class="nam">auth</span> <span class="key">import</span> <span class="nam">get_user_model</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">from</span> <span class="op">.</span><span class="nam">models</span> <span class="key">import</span> <span class="nam">Event</span><span class="op">,</span> <span class="nam">Task</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span><span class="op">.</span><span class="nam">test</span> <span class="key">import</span> <span class="nam">APIClient</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="key">import</span> <span class="nam">json</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"><span class="nam">User</span> <span class="op">=</span> <span class="nam">get_user_model</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"><span class="key">class</span> <span class="nam">EventModelTest</span><span class="op">(</span><span class="nam">TestCase</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="key">def</span> <span class="nam">setUp</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">user</span> <span class="op">=</span> <span class="nam">User</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create_user</span><span class="op">(</span><span class="nam">username</span><span class="op">=</span><span class="str">'testuser'</span><span class="op">,</span> <span class="nam">password</span><span class="op">=</span><span class="str">'testpass'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">event</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">title</span><span class="op">=</span><span class="str">'Test Event'</span><span class="op">,</span> <span class="nam">date</span><span class="op">=</span><span class="str">'2025-01-01'</span><span class="op">,</span> <span class="nam">time</span><span class="op">=</span><span class="str">'12:00'</span><span class="op">,</span> <span class="nam">description</span><span class="op">=</span><span class="str">'desc'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_str</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">str</span><span class="op">(</span><span class="nam">self</span><span class="op">.</span><span class="nam">event</span><span class="op">)</span><span class="op">,</span> <span class="str">'Test Event'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"><span class="key">class</span> <span class="nam">TaskModelTest</span><span class="op">(</span><span class="nam">TestCase</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="key">def</span> <span class="nam">setUp</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">user</span> <span class="op">=</span> <span class="nam">User</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create_user</span><span class="op">(</span><span class="nam">username</span><span class="op">=</span><span class="str">'testuser2'</span><span class="op">,</span> <span class="nam">password</span><span class="op">=</span><span class="str">'testpass'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">event</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">title</span><span class="op">=</span><span class="str">'Test Event'</span><span class="op">,</span> <span class="nam">date</span><span class="op">=</span><span class="str">'2025-01-01'</span><span class="op">,</span> <span class="nam">time</span><span class="op">=</span><span class="str">'12:00'</span><span class="op">,</span> <span class="nam">description</span><span class="op">=</span><span class="str">'desc'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">task</span> <span class="op">=</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">text</span><span class="op">=</span><span class="str">'Test Task'</span><span class="op">,</span> <span class="nam">event</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">event</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_str</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">str</span><span class="op">(</span><span class="nam">self</span><span class="op">.</span><span class="nam">task</span><span class="op">)</span><span class="op">,</span> <span class="str">'Test Task'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t"><span class="key">class</span> <span class="nam">ScheduleApiTest</span><span class="op">(</span><span class="nam">TestCase</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="key">def</span> <span class="nam">setUp</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span> <span class="op">=</span> <span class="nam">Client</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">user</span> <span class="op">=</span> <span class="nam">User</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create_user</span><span class="op">(</span><span class="nam">username</span><span class="op">=</span><span class="str">'testuser3'</span><span class="op">,</span> <span class="nam">password</span><span class="op">=</span><span class="str">'testpass'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">login</span><span class="op">(</span><span class="nam">username</span><span class="op">=</span><span class="str">'testuser3'</span><span class="op">,</span> <span class="nam">password</span><span class="op">=</span><span class="str">'testpass'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_event_list_api</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'event-list'</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertIn</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="op">[</span><span class="num">200</span><span class="op">,</span> <span class="num">403</span><span class="op">,</span> <span class="num">401</span><span class="op">]</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"><span class="key">class</span> <span class="nam">ScheduleViewsTest</span><span class="op">(</span><span class="nam">TestCase</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t"> <span class="key">def</span> <span class="nam">setUp</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span> <span class="op">=</span> <span class="nam">APIClient</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">user</span> <span class="op">=</span> <span class="nam">User</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create_user</span><span class="op">(</span><span class="nam">username</span><span class="op">=</span><span class="str">'testuser4'</span><span class="op">,</span> <span class="nam">password</span><span class="op">=</span><span class="str">'testpass'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">force_authenticate</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">event</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">title</span><span class="op">=</span><span class="str">'Event'</span><span class="op">,</span> <span class="nam">date</span><span class="op">=</span><span class="str">'2025-01-01'</span><span class="op">,</span> <span class="nam">time</span><span class="op">=</span><span class="str">'12:00'</span><span class="op">,</span> <span class="nam">description</span><span class="op">=</span><span class="str">'desc'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">task</span> <span class="op">=</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">create</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">text</span><span class="op">=</span><span class="str">'Task'</span><span class="op">,</span> <span class="nam">event</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">event</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_event_list_unauthenticated</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">force_authenticate</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="key">None</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'event-list'</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t48" href="#t48">48</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">401</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t49" href="#t49">49</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t50" href="#t50">50</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_event_detail_not_exist</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t51" href="#t51">51</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'event-detail'</span><span class="op">,</span> <span class="nam">args</span><span class="op">=</span><span class="op">[</span><span class="num">9999</span><span class="op">]</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t52" href="#t52">52</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">404</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t53" href="#t53">53</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t54" href="#t54">54</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_task_toggle_complete_not_exist</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t55" href="#t55">55</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">post</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'task-toggle'</span><span class="op">,</span> <span class="nam">args</span><span class="op">=</span><span class="op">[</span><span class="num">9999</span><span class="op">]</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t56" href="#t56">56</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">404</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t57" href="#t57">57</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t58" href="#t58">58</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_task_delete_not_exist</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t59" href="#t59">59</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">delete</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'task-delete'</span><span class="op">,</span> <span class="nam">args</span><span class="op">=</span><span class="op">[</span><span class="num">9999</span><span class="op">]</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t60" href="#t60">60</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">404</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t61" href="#t61">61</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t62" href="#t62">62</a></span><span class="t"> <span class="key">def</span> <span class="nam">test_today_events_unauthenticated</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t63" href="#t63">63</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">force_authenticate</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="key">None</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t64" href="#t64">64</a></span><span class="t"> <span class="nam">response</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">client</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">reverse</span><span class="op">(</span><span class="str">'today-events'</span><span class="op">)</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t65" href="#t65">65</a></span><span class="t"> <span class="nam">self</span><span class="op">.</span><span class="nam">assertEqual</span><span class="op">(</span><span class="nam">response</span><span class="op">.</span><span class="nam">status_code</span><span class="op">,</span> <span class="num">401</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_serializers_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_urls_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
</div>
</footer>
</body>
</html>

+ 117
- 0
htmlcov/z_5c71e8f1e4812293_urls_py.html View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/urls.py: 100%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/urls.py</b>:
<span class="pc_cov">100%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">3 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">3<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">0<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_tests_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_5c71e8f1e4812293_views_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># Schedule/urls.py</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">urls</span> <span class="key">import</span> <span class="nam">path</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="op">.</span><span class="nam">views</span> <span class="key">import</span> <span class="op">(</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"> <span class="nam">EventListCreateView</span><span class="op">,</span> <span class="nam">EventDetailView</span><span class="op">,</span> <span class="nam">ScheduleView</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">TaskListCreateView</span><span class="op">,</span> <span class="nam">TaskToggleCompleteView</span><span class="op">,</span> <span class="nam">TaskDeleteView</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="nam">TodayEventsView</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"><span class="nam">urlpatterns</span> <span class="op">=</span> <span class="op">[</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="com"># &#20107;&#20214;API</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'events/'</span><span class="op">,</span> <span class="nam">EventListCreateView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'event-list'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'events/&lt;int:pk>/'</span><span class="op">,</span> <span class="nam">EventDetailView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'event-detail'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'events/today/'</span><span class="op">,</span> <span class="nam">TodayEventsView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'today-events'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="com"># &#20219;&#21153;API</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'tasks/'</span><span class="op">,</span> <span class="nam">TaskListCreateView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'task-list'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'tasks/&lt;int:pk>/toggle/'</span><span class="op">,</span> <span class="nam">TaskToggleCompleteView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'task-toggle'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">'tasks/&lt;int:pk>/delete/'</span><span class="op">,</span> <span class="nam">TaskDeleteView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'task-delete'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">path</span><span class="op">(</span><span class="str">''</span><span class="op">,</span> <span class="nam">ScheduleView</span><span class="op">.</span><span class="nam">as_view</span><span class="op">(</span><span class="op">)</span><span class="op">,</span> <span class="nam">name</span><span class="op">=</span><span class="str">'schedule'</span><span class="op">)</span><span class="op">,</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_tests_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_5c71e8f1e4812293_views_py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 17:34 +0800
</p>
</div>
</footer>
</body>
</html>

+ 191
- 0
htmlcov/z_5c71e8f1e4812293_views_py.html View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for Schedule/views.py: 67%</title>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_6fb7b396.js" defer></script>
</head>
<body class="pyfile">
<header>
<div class="content">
<h1>
<span class="text">Coverage for </span><b>Schedule/views.py</b>:
<span class="pc_cov">67%</span>
</h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
<div class="keyhelp">
<p>
<kbd>r</kbd>
<kbd>m</kbd>
<kbd>x</kbd>
&nbsp; toggle line displays
</p>
<p>
<kbd>j</kbd>
<kbd>k</kbd>
&nbsp; next/prev highlighted chunk
</p>
<p>
<kbd>0</kbd> &nbsp; (zero) top of page
</p>
<p>
<kbd>1</kbd> &nbsp; (one) first highlighted chunk
</p>
<p>
<kbd>[</kbd>
<kbd>]</kbd>
&nbsp; prev/next file
</p>
<p>
<kbd>u</kbd> &nbsp; up to the index
</p>
<p>
<kbd>?</kbd> &nbsp; show/hide this help
</p>
</div>
</div>
</aside>
<h2>
<span class="text">67 statements &nbsp;</span>
<button type="button" class="run button_toggle_run" value="run" data-shortcut="r" title="Toggle lines run">45<span class="text"> run</span></button>
<button type="button" class="mis show_mis button_toggle_mis" value="mis" data-shortcut="m" title="Toggle lines missing">22<span class="text"> missing</span></button>
<button type="button" class="exc show_exc button_toggle_exc" value="exc" data-shortcut="x" title="Toggle lines excluded">0<span class="text"> excluded</span></button>
</h2>
<p class="text">
<a id="prevFileLink" class="nav" href="z_5c71e8f1e4812293_urls_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="z_c450d40fba27812a___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
<button type="button" class="button_prev_chunk" data-shortcut="k"></button>
<button type="button" class="button_top_of_page" data-shortcut="0"></button>
<button type="button" class="button_first_chunk" data-shortcut="1"></button>
<button type="button" class="button_prev_file" data-shortcut="["></button>
<button type="button" class="button_next_file" data-shortcut="]"></button>
<button type="button" class="button_to_index" data-shortcut="u"></button>
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
</aside>
</div>
</header>
<main id="source">
<p class="pln"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="com"># schedule/views.py</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span> <span class="key">import</span> <span class="nam">generics</span><span class="op">,</span> <span class="nam">status</span> <span class="com"># type: ignore</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span><span class="op">.</span><span class="nam">response</span> <span class="key">import</span> <span class="nam">Response</span> <span class="com"># type: ignore</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span><span class="op">.</span><span class="nam">permissions</span> <span class="key">import</span> <span class="nam">IsAuthenticated</span> <span class="com"># type: ignore</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"><span class="key">from</span> <span class="nam">rest_framework</span><span class="op">.</span><span class="nam">views</span> <span class="key">import</span> <span class="nam">APIView</span> <span class="com"># type: ignore</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">shortcuts</span> <span class="key">import</span> <span class="nam">get_object_or_404</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">utils</span> <span class="key">import</span> <span class="nam">timezone</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"><span class="key">from</span> <span class="op">.</span><span class="nam">models</span> <span class="key">import</span> <span class="nam">Event</span><span class="op">,</span> <span class="nam">Task</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"><span class="key">from</span> <span class="op">.</span><span class="nam">serializers</span> <span class="key">import</span> <span class="nam">EventSerializer</span><span class="op">,</span> <span class="nam">TaskSerializer</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">shortcuts</span> <span class="key">import</span> <span class="nam">render</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">views</span><span class="op">.</span><span class="nam">generic</span> <span class="key">import</span> <span class="nam">TemplateView</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"><span class="key">class</span> <span class="nam">EventListCreateView</span><span class="op">(</span><span class="nam">generics</span><span class="op">.</span><span class="nam">ListCreateAPIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="nam">serializer_class</span> <span class="op">=</span> <span class="nam">EventSerializer</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="key">def</span> <span class="nam">get_queryset</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> <span class="com"># &#33719;&#21462;&#26085;&#26399;&#33539;&#22260;&#21442;&#25968;</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t19" href="#t19">19</a></span><span class="t"> <span class="nam">start_date</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">query_params</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="str">'start_date'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t20" href="#t20">20</a></span><span class="t"> <span class="nam">end_date</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">query_params</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="str">'end_date'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t21" href="#t21">21</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t22" href="#t22">22</a></span><span class="t"> <span class="nam">queryset</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t23" href="#t23">23</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t24" href="#t24">24</a></span><span class="t"> <span class="com"># &#22914;&#26524;&#25552;&#20379;&#20102;&#26085;&#26399;&#33539;&#22260;&#65292;&#36827;&#34892;&#36807;&#28388;</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t25" href="#t25">25</a></span><span class="t"> <span class="key">if</span> <span class="nam">start_date</span> <span class="key">and</span> <span class="nam">end_date</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t26" href="#t26">26</a></span><span class="t"> <span class="nam">queryset</span> <span class="op">=</span> <span class="nam">queryset</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">date__range</span><span class="op">=</span><span class="op">[</span><span class="nam">start_date</span><span class="op">,</span> <span class="nam">end_date</span><span class="op">]</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t27" href="#t27">27</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t28" href="#t28">28</a></span><span class="t"> <span class="com"># &#25353;&#26085;&#26399;&#21644;&#26102;&#38388;&#25490;&#24207;</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t29" href="#t29">29</a></span><span class="t"> <span class="key">return</span> <span class="nam">queryset</span><span class="op">.</span><span class="nam">order_by</span><span class="op">(</span><span class="str">'date'</span><span class="op">,</span> <span class="str">'time'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t30" href="#t30">30</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t31" href="#t31">31</a></span><span class="t"> <span class="key">def</span> <span class="nam">perform_create</span><span class="op">(</span><span class="nam">self</span><span class="op">,</span> <span class="nam">serializer</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t32" href="#t32">32</a></span><span class="t"> <span class="nam">serializer</span><span class="op">.</span><span class="nam">save</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t33" href="#t33">33</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t34" href="#t34">34</a></span><span class="t"><span class="key">class</span> <span class="nam">EventDetailView</span><span class="op">(</span><span class="nam">generics</span><span class="op">.</span><span class="nam">RetrieveUpdateDestroyAPIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t35" href="#t35">35</a></span><span class="t"> <span class="nam">queryset</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">all</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t36" href="#t36">36</a></span><span class="t"> <span class="nam">serializer_class</span> <span class="op">=</span> <span class="nam">EventSerializer</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t37" href="#t37">37</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t38" href="#t38">38</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t39" href="#t39">39</a></span><span class="t"> <span class="key">def</span> <span class="nam">get_queryset</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t40" href="#t40">40</a></span><span class="t"> <span class="key">return</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t41" href="#t41">41</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t42" href="#t42">42</a></span><span class="t"><span class="key">class</span> <span class="nam">TaskListCreateView</span><span class="op">(</span><span class="nam">generics</span><span class="op">.</span><span class="nam">ListCreateAPIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t43" href="#t43">43</a></span><span class="t"> <span class="nam">serializer_class</span> <span class="op">=</span> <span class="nam">TaskSerializer</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t44" href="#t44">44</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t45" href="#t45">45</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t46" href="#t46">46</a></span><span class="t"> <span class="key">def</span> <span class="nam">get_queryset</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t47" href="#t47">47</a></span><span class="t"> <span class="com"># &#22914;&#26524;&#25552;&#20379;&#20102;date&#21442;&#25968;&#65292;&#36807;&#28388;&#24403;&#22825;&#30340;&#20219;&#21153;</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t48" href="#t48">48</a></span><span class="t"> <span class="nam">date</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">query_params</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="str">'date'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t49" href="#t49">49</a></span><span class="t"> <span class="key">if</span> <span class="nam">date</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t50" href="#t50">50</a></span><span class="t"> <span class="key">return</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">event__date</span><span class="op">=</span><span class="nam">date</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t51" href="#t51">51</a></span><span class="t"> <span class="com"># &#40664;&#35748;&#36820;&#22238;&#25152;&#26377;&#20219;&#21153;</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t52" href="#t52">52</a></span><span class="t"> <span class="key">return</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t53" href="#t53">53</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t54" href="#t54">54</a></span><span class="t"> <span class="key">def</span> <span class="nam">perform_create</span><span class="op">(</span><span class="nam">self</span><span class="op">,</span> <span class="nam">serializer</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t55" href="#t55">55</a></span><span class="t"> <span class="com"># &#22914;&#26524;&#35831;&#27714;&#20013;&#21253;&#21547;event_id&#65292;&#20851;&#32852;&#21040;&#23545;&#24212;&#30340;&#20107;&#20214;</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t56" href="#t56">56</a></span><span class="t"> <span class="nam">event_id</span> <span class="op">=</span> <span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">data</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="str">'event'</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t57" href="#t57">57</a></span><span class="t"> <span class="key">if</span> <span class="nam">event_id</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t58" href="#t58">58</a></span><span class="t"> <span class="key">try</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t59" href="#t59">59</a></span><span class="t"> <span class="nam">event</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">get</span><span class="op">(</span><span class="nam">id</span><span class="op">=</span><span class="nam">event_id</span><span class="op">,</span> <span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t60" href="#t60">60</a></span><span class="t"> <span class="nam">serializer</span><span class="op">.</span><span class="nam">save</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">event</span><span class="op">=</span><span class="nam">event</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t61" href="#t61">61</a></span><span class="t"> <span class="key">except</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">DoesNotExist</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t62" href="#t62">62</a></span><span class="t"> <span class="key">return</span> <span class="nam">Response</span><span class="op">(</span><span class="op">{</span><span class="str">"error"</span><span class="op">:</span> <span class="str">"Event not found"</span><span class="op">}</span><span class="op">,</span> <span class="nam">status</span><span class="op">=</span><span class="nam">status</span><span class="op">.</span><span class="nam">HTTP_400_BAD_REQUEST</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t63" href="#t63">63</a></span><span class="t"> <span class="key">else</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t64" href="#t64">64</a></span><span class="t"> <span class="nam">serializer</span><span class="op">.</span><span class="nam">save</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t65" href="#t65">65</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t66" href="#t66">66</a></span><span class="t"><span class="key">class</span> <span class="nam">TaskToggleCompleteView</span><span class="op">(</span><span class="nam">APIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t67" href="#t67">67</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t68" href="#t68">68</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t69" href="#t69">69</a></span><span class="t"> <span class="key">def</span> <span class="nam">post</span><span class="op">(</span><span class="nam">self</span><span class="op">,</span> <span class="nam">request</span><span class="op">,</span> <span class="nam">pk</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t70" href="#t70">70</a></span><span class="t"> <span class="nam">task</span> <span class="op">=</span> <span class="nam">get_object_or_404</span><span class="op">(</span><span class="nam">Task</span><span class="op">,</span> <span class="nam">id</span><span class="op">=</span><span class="nam">pk</span><span class="op">,</span> <span class="nam">user</span><span class="op">=</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t71" href="#t71">71</a></span><span class="t"> <span class="nam">task</span><span class="op">.</span><span class="nam">completed</span> <span class="op">=</span> <span class="key">not</span> <span class="nam">task</span><span class="op">.</span><span class="nam">completed</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t72" href="#t72">72</a></span><span class="t"> <span class="nam">task</span><span class="op">.</span><span class="nam">save</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t73" href="#t73">73</a></span><span class="t"> <span class="nam">serializer</span> <span class="op">=</span> <span class="nam">TaskSerializer</span><span class="op">(</span><span class="nam">task</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t74" href="#t74">74</a></span><span class="t"> <span class="key">return</span> <span class="nam">Response</span><span class="op">(</span><span class="nam">serializer</span><span class="op">.</span><span class="nam">data</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t75" href="#t75">75</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t76" href="#t76">76</a></span><span class="t"><span class="key">class</span> <span class="nam">TaskDeleteView</span><span class="op">(</span><span class="nam">generics</span><span class="op">.</span><span class="nam">DestroyAPIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t77" href="#t77">77</a></span><span class="t"> <span class="nam">queryset</span> <span class="op">=</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">all</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t78" href="#t78">78</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t79" href="#t79">79</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t80" href="#t80">80</a></span><span class="t"> <span class="key">def</span> <span class="nam">get_queryset</span><span class="op">(</span><span class="nam">self</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t81" href="#t81">81</a></span><span class="t"> <span class="key">return</span> <span class="nam">Task</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">self</span><span class="op">.</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t82" href="#t82">82</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t83" href="#t83">83</a></span><span class="t"><span class="key">class</span> <span class="nam">TodayEventsView</span><span class="op">(</span><span class="nam">APIView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t84" href="#t84">84</a></span><span class="t"> <span class="nam">permission_classes</span> <span class="op">=</span> <span class="op">[</span><span class="nam">IsAuthenticated</span><span class="op">]</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t85" href="#t85">85</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t86" href="#t86">86</a></span><span class="t"> <span class="key">def</span> <span class="nam">get</span><span class="op">(</span><span class="nam">self</span><span class="op">,</span> <span class="nam">request</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t87" href="#t87">87</a></span><span class="t"> <span class="nam">today</span> <span class="op">=</span> <span class="nam">timezone</span><span class="op">.</span><span class="nam">now</span><span class="op">(</span><span class="op">)</span><span class="op">.</span><span class="nam">date</span><span class="op">(</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t88" href="#t88">88</a></span><span class="t"> <span class="nam">events</span> <span class="op">=</span> <span class="nam">Event</span><span class="op">.</span><span class="nam">objects</span><span class="op">.</span><span class="nam">filter</span><span class="op">(</span><span class="nam">user</span><span class="op">=</span><span class="nam">request</span><span class="op">.</span><span class="nam">user</span><span class="op">,</span> <span class="nam">date</span><span class="op">=</span><span class="nam">today</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t89" href="#t89">89</a></span><span class="t"> <span class="nam">serializer</span> <span class="op">=</span> <span class="nam">EventSerializer</span><span class="op">(</span><span class="nam">events</span><span class="op">,</span> <span class="nam">many</span><span class="op">=</span><span class="key">True</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="mis show_mis"><span class="n"><a id="t90" href="#t90">90</a></span><span class="t"> <span class="key">return</span> <span class="nam">Response</span><span class="op">(</span><span class="nam">serializer</span><span class="op">.</span><span class="nam">data</span><span class="op">)</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t91" href="#t91">91</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t92" href="#t92">92</a></span><span class="t"><span class="key">class</span> <span class="nam">ScheduleView</span><span class="op">(</span><span class="nam">TemplateView</span><span class="op">)</span><span class="op">:</span>&nbsp;</span><span class="r"></span></p>
<p class="run"><span class="n"><a id="t93" href="#t93">93</a></span><span class="t"> <span class="nam">template_name</span> <span class="op">=</span> <span class="str">'Schedule.html'</span>&nbsp;</span><span class="r"></span></p>
<p class="pln"><span class="n"><a id="t94" href="#t94">94</a></span><span class="t">&nbsp;</span><span class="r"></span></p>
</main>
<footer>
<div class="content">
<p>
<a class="nav" href="z_5c71e8f1e4812293_urls_py.html">&#xab; prev</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="z_c450d40fba27812a___init___py.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.7.1">coverage.py v7.7.1</a>,
created at 2025-07-22 19:12 +0800
</p>
</div>
</footer>
</body>
</html>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save