Selaa lähdekoodia

添加分组管理

刘凡 2 vuotta sitten
vanhempi
commit
bd9822a16a
43 muutettua tiedostoa jossa 1249 lisäystä ja 82 poistoa
  1. 2 1
      .idea/vcs.xml
  2. 1 1
      Config/database_mysql.cnf
  3. 2 1
      TestLaboratory/settings.py
  4. 2 1
      TestLaboratory/urls.py
  5. 0 0
      apps/group/__init__.py
  6. 3 0
      apps/group/admin.py
  7. 6 0
      apps/group/apps.py
  8. 31 0
      apps/group/migrations/0001_initial.py
  9. 19 0
      apps/group/migrations/0002_group_users.py
  10. 18 0
      apps/group/migrations/0003_alter_group_code.py
  11. 0 0
      apps/group/migrations/__init__.py
  12. 25 0
      apps/group/models.py
  13. 3 0
      apps/group/tests.py
  14. 10 0
      apps/group/urls.py
  15. 3 0
      apps/group/views.py
  16. 0 0
      apps/group/views/__init__.py
  17. 81 0
      apps/group/views/grouplistview.py
  18. 57 0
      apps/group/views/groupview.py
  19. 23 0
      apps/software/migrations/0003_auto_20221004_2044.py
  20. 2 2
      apps/software/models.py
  21. 18 0
      apps/task/migrations/0004_alter_testcase_id.py
  22. 1 1
      apps/task/models.py
  23. 17 0
      apps/user/migrations/0003_remove_user_group.py
  24. 1 1
      apps/user/models.py
  25. 5 0
      apps/user/urls.py
  26. 36 0
      apps/user/views/userjoinview.py
  27. 9 27
      apps/user/views/userlistview.py
  28. 36 0
      apps/user/views/userquitview.py
  29. 6 6
      apps/user/views/userview.py
  30. BIN
      db/permission.xlsx
  31. BIN
      db/role_permissions.xlsx
  32. BIN
      db/software.xlsx
  33. 14 0
      logs/all-2022-10-04.log
  34. 74 0
      logs/all-2022-10-05.log
  35. 553 0
      logs/all-2022-10-06.log
  36. 0 0
      logs/error-2022-10-04.log
  37. 0 0
      logs/error-2022-10-05.log
  38. 0 0
      logs/error-2022-10-06.log
  39. 0 0
      logs/info-2022-10-04.log
  40. 0 0
      logs/info-2022-10-05.log
  41. 0 0
      logs/info-2022-10-06.log
  42. 102 41
      mysql-init/TestLaboratory.sql
  43. 89 0
      utils/util_random.py

+ 2 - 1
.idea/vcs.xml

@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
+    <mapping directory="$USER_HOME$" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
     <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
   </component>
 </project>

+ 1 - 1
Config/database_mysql.cnf

@@ -1,5 +1,5 @@
 [client]
-host = 127.0.0.1
+host = db
 port = 3306
 database = TestLaboratory
 user = root

+ 2 - 1
TestLaboratory/settings.py

@@ -63,7 +63,8 @@ INSTALLED_APPS = [
     'plan',
     'apps.task',
     'file',
-    'log'
+    'log',
+    'group'
 ]
 
 MIDDLEWARE = [

+ 2 - 1
TestLaboratory/urls.py

@@ -24,5 +24,6 @@ urlpatterns = [
     path('api/v1/test-plans/', include('plan.urls')),
     path('api/v1/test-tasks/', include('task.urls')),
     path('api/v1/log-info/', include('log.urls')),
-    path('api/v1/files/', include('file.urls'))
+    path('api/v1/files/', include('file.urls')),
+    path('api/v1/group/', include('group.urls'))
 ] + static(settings.STATIC_URL, document_root=settings.STATICFILES_DIRS)

+ 0 - 0
apps/group/__init__.py


+ 3 - 0
apps/group/admin.py

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

+ 6 - 0
apps/group/apps.py

@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class GroupConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'apps.group'

+ 31 - 0
apps/group/migrations/0001_initial.py

@@ -0,0 +1,31 @@
+# Generated by Django 3.2.4 on 2022-10-04 20:49
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Group',
+            fields=[
+                ('name', models.CharField(max_length=128, verbose_name='组名')),
+                ('id', models.CharField(default='TestLaboratory_V1_Group_1', max_length=128, primary_key=True, serialize=False, unique=True, verbose_name='分组id')),
+                ('code', models.IntegerField(verbose_name='分组code')),
+                ('manager', models.CharField(max_length=60, verbose_name='管理员id')),
+                ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+                ('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
+                ('delete', models.BooleanField(default=False)),
+            ],
+            options={
+                'verbose_name': '被测试软件',
+                'verbose_name_plural': '被测试软件',
+                'db_table': 'group',
+            },
+        ),
+    ]

+ 19 - 0
apps/group/migrations/0002_group_users.py

@@ -0,0 +1,19 @@
+# Generated by Django 3.2.4 on 2022-10-05 17:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0003_remove_user_group'),
+        ('group', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='group',
+            name='users',
+            field=models.ManyToManyField(to='user.User', verbose_name='成员'),
+        ),
+    ]

+ 18 - 0
apps/group/migrations/0003_alter_group_code.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.4 on 2022-10-05 19:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('group', '0002_group_users'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='group',
+            name='code',
+            field=models.CharField(max_length=12, verbose_name='分组code'),
+        ),
+    ]

+ 0 - 0
apps/group/migrations/__init__.py


+ 25 - 0
apps/group/models.py

@@ -0,0 +1,25 @@
+from django.db import models
+
+
+# Create your models here.
+from apps.user.models import User
+
+
+class Group(models.Model):
+    name = models.CharField(max_length=128, verbose_name='组名')
+    id = models.CharField(max_length=128, unique=True, primary_key=True, verbose_name='分组id',
+                          default='TestLaboratory_V1_Group_1')
+    code = models.CharField(max_length=12, verbose_name='分组code')
+    manager = models.CharField(max_length=60, verbose_name='管理员id')
+    users = models.ManyToManyField(User, verbose_name='成员')
+    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
+    update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
+    delete = models.BooleanField(default=False)
+
+    def __str__(self):
+        return self.name
+
+    class Meta:
+        verbose_name = '被测试软件'
+        verbose_name_plural = verbose_name
+        db_table = 'group'

+ 3 - 0
apps/group/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 10 - 0
apps/group/urls.py

@@ -0,0 +1,10 @@
+from django.urls import path
+from .views.grouplistview import GroupListView
+from .views.groupview import GroupView, GroupEdit
+
+urlpatterns = [
+    path('', GroupListView.as_view()),
+    path('<str:group_id>', GroupView.as_view()),
+    path('<str:group_id>/edit', GroupEdit.as_view()),
+
+]

+ 3 - 0
apps/group/views.py

@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.

+ 0 - 0
apps/group/views/__init__.py


+ 81 - 0
apps/group/views/grouplistview.py

@@ -0,0 +1,81 @@
+import datetime
+import logging
+
+from django.http import HttpResponse
+from rest_framework.views import APIView
+from rest_framework.response import Response
+
+from apps.group.models import Group
+from apps.log.models import get_log, gen_log
+from apps.user.middleware.rolecontrol import RoleControl
+from apps.user.models import User
+from utils.util_add_id import get_id
+from utils.util_random import Produce
+
+logger = logging.getLogger('django')
+
+
+class GroupListView(APIView):
+    # create group
+    @staticmethod
+    @RoleControl
+    def post(request, *args, **kwargs):
+        name = request.POST.get('name')
+        manager_id = request.POST.get('manager_id')
+        manager = User.objects.filter(id=manager_id)[0]
+        group = Group.objects.filter(name=name, delete=False)
+        if group:
+            logger.error("组名已存在,请修改组名重新上传")
+            return HttpResponse(status=500, content='组名已存在,请修改组名重新上传')
+        create_time = update_time = datetime.datetime.now()
+        group_id = get_id(Group, 'TestLaboratory_V1_Group_1')
+        code = Produce.auth_code(option='num')
+        group = Group.objects.create(id=group_id, code=code, manager=manager_id, name=name, create_time=create_time,
+                                     update_time=update_time)
+        executor, action, method = get_log(request)
+        gen_log(action, "分组", group.name, method, executor)
+        return Response({
+            'id': group.id,
+            'name': group.name,
+            'code': group.code,
+            'manager': manager.username,
+        })
+
+    # view log_list
+    @staticmethod
+    @RoleControl
+    def get(request, *args, **kwargs):
+        group_id = request.GET.get('id')
+        name = request.GET.get('name')
+        code = request.GET.get('code')
+        manager_id = request.GET.get('manager_id')
+
+        groups = Group.objects.order_by('-create_time').filter(delete=False)
+        if group_id:
+            groups = groups.filter(id=group_id)
+        if name:
+            groups = groups.filter(name=name)
+        if code:
+            groups = groups.filter(code=code)
+        if manager_id:
+            groups = groups.filter(manager=manager_id)
+
+        return_groups = list()
+        for group in groups:
+            manager = User.objects.filter(id=group.manager)[0]
+            user_info = list()
+            users = group.users.order_by('-create_time')
+            for user in users:
+                user_info.append({
+                    'id': user.id,
+                    'username': user.username,
+                    'identity': user.identify
+                })
+            return_groups.append({
+                'id': group.id,
+                'name': group.name,
+                'code': group.code,
+                'manager': manager.username,
+                'members': user_info
+            })
+        return Response(return_groups)

+ 57 - 0
apps/group/views/groupview.py

@@ -0,0 +1,57 @@
+from django.http import HttpResponse
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from apps.group.models import Group
+from apps.log.models import get_log, gen_log
+from apps.user.middleware.rolecontrol import RoleControl
+from apps.user.models import User
+
+import logging
+logger = logging.getLogger('django')
+
+
+class GroupView(APIView):
+    authentication_classes = []
+
+    # 删除分组
+    @staticmethod
+    @RoleControl
+    def delete(request, group_id, *args, **kwargs):
+        group = Group.objects.filter(id=group_id, delete=False)
+        if not group:
+            logger.error("分组已删除或不存在")
+        group = group[0]
+        users = group.users.all()
+        for user in users:
+            group.users.remove(user)
+        group.delete = True
+        group.save()
+        executor, action, method = get_log(request)
+        gen_log(action, "分组", group.name, method, executor)
+        return HttpResponse("删除完成")
+
+
+class GroupEdit(APIView):
+    authentication_classes = []
+
+    # 编辑分组
+    @staticmethod
+    @RoleControl
+    def post(request, group_id, *args, **kwargs):
+        name = request.POST.get('group_name')
+
+        if not name:
+            logger.error("组名不能位空")
+            return HttpResponse(status=500, content='组名不能位空')
+
+        group = Group.objects.filter(id=group_id, delete=False)
+        if not group:
+            logger.error("id为" + group_id + "的分组不存在")
+            return HttpResponse(status=404, content="id为" + group_id + "的分组不存在")
+        group = group[0]
+        group.name = name
+        group.save()
+        executor, action, method = get_log(request)
+        gen_log(action, "分组", group.name, method, executor)
+        return HttpResponse(status=200, content='修改已保存')

+ 23 - 0
apps/software/migrations/0003_auto_20221004_2044.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.2.4 on 2022-10-04 20:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('software', '0002_alter_software_name'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='software',
+            name='id',
+            field=models.CharField(default='TestLaboratory_V1_Software_1', max_length=128, primary_key=True, serialize=False, unique=True, verbose_name='被测试软件编号'),
+        ),
+        migrations.AlterField(
+            model_name='version',
+            name='id',
+            field=models.CharField(default='TestLaboratory_V1_Version_1', max_length=128, primary_key=True, serialize=False, unique=True, verbose_name='软件版本'),
+        ),
+    ]

+ 2 - 2
apps/software/models.py

@@ -10,7 +10,7 @@ from utils.util_create_file import create_version_file
 
 class Software(models.Model):
     name = models.CharField(max_length=128, verbose_name='被测试软件名')
-    id = models.CharField(max_length=30, unique=True, primary_key=True, verbose_name='被测试软件编号',
+    id = models.CharField(max_length=128, unique=True, primary_key=True, verbose_name='被测试软件编号',
                           default='TestLaboratory_V1_Software_1')
     type = models.CharField(max_length=20, verbose_name='被测试软件类型')
     report_file = models.TextField(null=True, verbose_name='测试报告id文件')
@@ -28,7 +28,7 @@ class Software(models.Model):
 
 
 class Version(models.Model):
-    id = models.CharField(max_length=30, unique=True, primary_key=True, verbose_name='软件版本',
+    id = models.CharField(max_length=128, unique=True, primary_key=True, verbose_name='软件版本',
                           default='TestLaboratory_V1_Version_1')
     number = models.CharField(max_length=20, verbose_name='版本号')
     software = models.ForeignKey(Software, on_delete=models.CASCADE, verbose_name='所属软件')

+ 18 - 0
apps/task/migrations/0004_alter_testcase_id.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.4 on 2022-10-04 20:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('task', '0003_auto_20220626_1630'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='testcase',
+            name='id',
+            field=models.CharField(default='TestLaboratory_V1_Case_1', max_length=128, primary_key=True, serialize=False, unique=True, verbose_name='测试用例编号'),
+        ),
+    ]

+ 1 - 1
apps/task/models.py

@@ -35,7 +35,7 @@ class TestTask(models.Model):
 
 
 class TestCase(models.Model):
-    id = models.CharField(max_length=30, unique=True, primary_key=True, verbose_name='测试用例编号',
+    id = models.CharField(max_length=128, unique=True, primary_key=True, verbose_name='测试用例编号',
                           default='TestLaboratory_V1_Case_1')
     task = models.ForeignKey(TestTask, on_delete=models.CASCADE, verbose_name='测试用例所在测试任务',
                              default='TestLaboratory_V1_Task_1')

+ 17 - 0
apps/user/migrations/0003_remove_user_group.py

@@ -0,0 +1,17 @@
+# Generated by Django 3.2.4 on 2022-10-05 17:30
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0002_auto_20220619_1043'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='user',
+            name='group',
+        ),
+    ]

+ 1 - 1
apps/user/models.py

@@ -51,7 +51,7 @@ class User(models.Model):
     tel = models.CharField(max_length=20, verbose_name='联系方式')
     identify = models.IntegerField(verbose_name='身份信息')
     roles = models.ManyToManyField(Role, blank=True, verbose_name='角色信息')
-    group = models.CharField(max_length=128, default='默认分组', verbose_name='分组')
+    # group = models.CharField(max_length=128, default='默认分组', verbose_name='分组')
     create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
     update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
     is_login = models.BooleanField(default=False)

+ 5 - 0
apps/user/urls.py

@@ -1,5 +1,8 @@
 from django.urls import path
+
+from .views.userjoinview import UserJoinView
 from .views.userlistview import UserListView, UserListLogin
+from .views.userquitview import UserQuitView
 from .views.userview import UserView, UserEdit
 
 urlpatterns = [
@@ -8,4 +11,6 @@ urlpatterns = [
     path('login', UserListLogin.as_view()),
     path('<str:user_id>', UserView.as_view()),
     path('<str:user_id>/edit', UserEdit.as_view()),
+    path('<str:user_id>/join', UserJoinView.as_view()),
+    path('<str:user_id>/quit', UserQuitView.as_view())
 ]

+ 36 - 0
apps/user/views/userjoinview.py

@@ -0,0 +1,36 @@
+import logging
+
+from django.http import HttpResponse
+from rest_framework.views import APIView
+
+from apps.group.models import Group
+from apps.log.models import get_log, gen_log
+from apps.user.middleware.rolecontrol import RoleControl
+from apps.user.models import User
+
+logger = logging.getLogger('django')
+
+
+class UserJoinView(APIView):
+    authentication_classes = []
+
+    @staticmethod
+    @RoleControl
+    def post(request, user_id, *args, **kwargs):
+        code = request.POST.get('code')
+        group = Group.objects.filter(code=code, delete=False)
+        if not group:
+            logger.error("分组不存在")
+            return HttpResponse(status=500, content='分组不存在')
+        group = group[0]
+
+        user = User.objects.filter(id=user_id)
+        if not user:
+            logger.error("用户不存在")
+            return HttpResponse(status=404, content='用户不存在')
+        user = user[0]
+
+        group.users.add(user)
+        executor, action, method = get_log(request)
+        gen_log(action, "加入分组", group.name, method, executor)
+        return HttpResponse(status=200, content='加入成功')

+ 9 - 27
apps/user/views/userlistview.py

@@ -25,7 +25,6 @@ class UserListView(APIView):
             'name': request.POST.get('name'),
             'tel': request.POST.get('tel'),
             'identify': request.POST.get('identify'),
-            'group': request.POST.get('group')
         }
 
         if not payload['username']:
@@ -34,8 +33,6 @@ class UserListView(APIView):
         if not payload['password']:
             logger.error("密码不能为空")
             return HttpResponse(status=500, content='密码不能为空')
-        if not payload['group']:
-            del payload['group']
         users = User.objects.filter(username=payload['username'])
         if users:
             logger.error("用户名已存在,请修改用户名重新上传")
@@ -46,7 +43,7 @@ class UserListView(APIView):
         payload['update_time'] = update_time
 
         payload['id'] = get_id(User, 'TestLaboratory_V1_User_1')
-        new_user = User.objects.create(**payload)
+        User.objects.create(**payload)
         return HttpResponse(status=200, content='创建成功')
 
     # user list
@@ -72,29 +69,15 @@ class UserListView(APIView):
             user_all = user_all.order_by(sort)
 
         users_info = []
-        user_group_index = {}
-        i = 0
         for user in user_all:
-            if user.group not in user_group_index.keys():
-                user_group_index[user.group] = i
-                i += 1
-                user_group = {'groupName': user.group, 'userList': [{
-                    'userid': user.id,
-                    'username': user.username,
-                    'identify': user.identify,
-                    'group': user.group,
-                    'is_login': user.is_login
-                }]}
-                users_info.append(user_group)
-            else:
-                users_info[user_group_index[user.group]]['userList'].append({
-                    'userid': user.id,
-                    'username': user.username,
-                    'identify': user.identify,
-                    'group': user.group,
-                    'is_login': user.is_login
-                })
-        return Response({'groupList': users_info})
+            users_info.append({
+                'userid': user.id,
+                'username': user.username,
+                'name': user.name,
+                'identify': user.identify,
+                'is_login': user.is_login
+            })
+        return Response(users_info)
 
 
 class UserListLogin(APIView):
@@ -122,7 +105,6 @@ class UserListLogin(APIView):
             'userid': user_obj.id,
             'username': user_obj.username,
             'identify': user_obj.identify,
-            'group': user_obj.group,
             'token': token
         }
 

+ 36 - 0
apps/user/views/userquitview.py

@@ -0,0 +1,36 @@
+import logging
+
+from django.http import HttpResponse
+from rest_framework.views import APIView
+
+from apps.group.models import Group
+from apps.log.models import get_log, gen_log
+from apps.user.middleware.rolecontrol import RoleControl
+from apps.user.models import User
+
+logger = logging.getLogger('django')
+
+
+class UserQuitView(APIView):
+    authentication_classes = []
+
+    @staticmethod
+    @RoleControl
+    def post(request, user_id, *args, **kwargs):
+        code = request.POST.get('code')
+        group = Group.objects.filter(code=code, delete=False)
+        if not group:
+            logger.error("分组不存在")
+            return HttpResponse(status=500, content='分组不存在')
+        group = group[0]
+
+        user = User.objects.filter(id=user_id)
+        if not user:
+            logger.error("用户不存在")
+            return HttpResponse(status=404, content='用户不存在')
+        user = user[0]
+
+        group.users.remove(user)
+        executor, action, method = get_log(request)
+        gen_log(action, "退出分组", group.name, method, executor)
+        return HttpResponse(status=200, content='退出成功')

+ 6 - 6
apps/user/views/userview.py

@@ -24,8 +24,7 @@ class UserView(APIView):
             'username': user.username,
             'name': user.name,
             'identify': user.identify,
-            'tel': user.tel,
-            'group': user.group
+            'tel': user.tel
         })
 
 
@@ -39,7 +38,6 @@ class UserEdit(APIView):
         username = request.POST.get('username')
         tel = request.POST.get('tel')
         password = request.POST.get('password')
-        group = request.POST.get('group')
 
         if not username:
             logger.error("用户名不能为空")
@@ -53,13 +51,15 @@ class UserEdit(APIView):
         if not user:
             logger.error("用户不存在")
             return HttpResponse(status=404, content='用户不存在')
+        other_user = User.objects.filter(username=username)
+        if other_user:
+            logger.error("用户名已存在,请修改用户名")
+            return HttpResponse(status=500, content='用户名已存在,请修改用户名')
         user = user[0]
         user.username = username
         user.password = password
         if tel:
             user.tel = tel
-        if group:
-            user.group = group
 
         user.save()
-        return HttpResponse(status=200, content='修改已保存')
+        return HttpResponse(status=200, content='修改已保存')

BIN
db/permission.xlsx


BIN
db/role_permissions.xlsx


BIN
db/software.xlsx


+ 14 - 0
logs/all-2022-10-04.log

@@ -0,0 +1,14 @@
+[INFO] [2022-10-04 19:20:26,236] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[WARNING] [2022-10-04 19:20:28,248] [log.py:224] [log:log_response] - Not Found: /
+[WARNING] [2022-10-04 19:20:28,248] [basehttp.py:161] [basehttp:log_message] - "GET / HTTP/1.1" 404 2782
+[WARNING] [2022-10-04 19:20:28,360] [log.py:224] [log:log_response] - Not Found: /favicon.ico
+[WARNING] [2022-10-04 19:20:28,360] [basehttp.py:161] [basehttp:log_message] - "GET /favicon.ico HTTP/1.1" 404 2833
+[INFO] [2022-10-04 19:20:42,348] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software HTTP/1.1" 301 0
+[WARNING] [2022-10-04 19:20:42,354] [log.py:224] [log:log_response] - Forbidden: /api/v1/software/
+[WARNING] [2022-10-04 19:20:42,354] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software/ HTTP/1.1" 403 37
+[INFO] [2022-10-04 19:23:18,706] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software HTTP/1.1" 301 0
+[WARNING] [2022-10-04 19:23:18,709] [log.py:224] [log:log_response] - Forbidden: /api/v1/software/
+[WARNING] [2022-10-04 19:23:18,709] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software/ HTTP/1.1" 403 43
+[INFO] [2022-10-04 19:23:27,284] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software HTTP/1.1" 301 0
+[WARNING] [2022-10-04 19:23:27,286] [log.py:224] [log:log_response] - Forbidden: /api/v1/software/
+[WARNING] [2022-10-04 19:23:27,286] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/software/ HTTP/1.1" 403 43

+ 74 - 0
logs/all-2022-10-05.log

@@ -0,0 +1,74 @@
+[INFO] [2022-10-05 19:38:38,957] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[ERROR] [2022-10-05 19:41:59,059] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/utils/deprecation.py", line 116, in __call__
+    response = self.process_request(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/middleware/common.py", line 54, in process_request
+    path = self.get_full_path_with_slash(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/middleware/common.py", line 88, in get_full_path_with_slash
+    raise RuntimeError(
+RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/api/v1/group/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
+[ERROR] [2022-10-05 19:41:59,060] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group HTTP/1.1" 500 73447
+[WARNING] [2022-10-05 19:42:51,380] [log.py:224] [log:log_response] - Forbidden: /api/v1/group/
+[WARNING] [2022-10-05 19:42:51,381] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 403 37
+[ERROR] [2022-10-05 19:42:58,516] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/login
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py", line 125, in post
+    'group': user_obj.group,
+AttributeError: 'User' object has no attribute 'group'
+[ERROR] [2022-10-05 19:42:58,517] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 500 94728
+[INFO] [2022-10-05 19:43:39,341] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py changed, reloading.
+[INFO] [2022-10-05 19:43:39,639] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-05 19:43:42,070] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 200 292
+[ERROR] [2022-10-05 19:44:00,289] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py", line 30, in post
+    Group.objects.create(id=group_id, code=code, manager_id=manager_id, name=name, create_time=create_time,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
+    return getattr(self.get_queryset(), name)(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/query.py", line 451, in create
+    obj = self.model(**kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 503, in __init__
+    raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
+TypeError: Group() got an unexpected keyword argument 'manager_id'
+[ERROR] [2022-10-05 19:44:00,293] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 500 116471
+[INFO] [2022-10-05 19:44:55,486] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-05 19:44:55,710] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-05 19:44:57,740] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 200 12
+[INFO] [2022-10-06 09:58:00,351] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/urls.py changed, reloading.

+ 553 - 0
logs/all-2022-10-06.log

@@ -0,0 +1,553 @@
+[INFO] [2022-10-06 09:58:00,720] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 09:59:00,305] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/urls.py changed, reloading.
+[INFO] [2022-10-06 09:59:00,523] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 09:59:19,344] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 09:59:19,565] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 09:59:48,415] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 09:59:48,626] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:03:40,770] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 10:03:41,037] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:06:20,058] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:06:20,371] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:06:29,931] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:06:30,222] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:08:37,175] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:08:37,486] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:09:00,541] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:09:00,839] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[ERROR] [2022-10-06 10:09:06,754] [grouplistview.py:27] [grouplistview:post] - 组名已存在,请修改组名重新上传
+[ERROR] [2022-10-06 10:09:06,754] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+[ERROR] [2022-10-06 10:09:06,754] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 500 45
+[INFO] [2022-10-06 10:09:12,044] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 200 89
+[ERROR] [2022-10-06 10:10:42,937] [groupview.py:23] [groupview:post] - 组名不能位空
+[ERROR] [2022-10-06 10:10:42,937] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/TestLaboratory_V1_Group_2/edit
+[ERROR] [2022-10-06 10:10:42,938] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/TestLaboratory_V1_Group_2/edit HTTP/1.1" 500 18
+[INFO] [2022-10-06 10:11:06,159] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/TestLaboratory_V1_Group_2/edit HTTP/1.1" 200 15
+[INFO] [2022-10-06 10:12:17,548] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:12:17,859] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:13:48,708] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:13:49,022] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:13:55,459] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:13:55,759] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:14:06,244] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:14:06,549] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:18:13,179] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:18:13,537] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:18:32,426] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:18:32,680] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:18:57,639] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:18:57,848] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:19:20,517] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:19:20,727] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:19:39,545] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:19:39,836] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:20:18,982] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:20:19,181] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:22:16,913] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:22:17,235] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:22:29,959] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:22:30,279] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:26:47,918] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:26:48,241] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:27:35,080] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:27:35,393] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:28:22,060] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:28:22,362] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:28:29,764] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:28:29,991] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:28:50,781] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:28:50,993] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:30:47,323] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:30:47,640] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[ERROR] [2022-10-06 10:31:21,296] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py", line 64, in get
+    for user in group.users:
+TypeError: 'ManyRelatedManager' object is not iterable
+[ERROR] [2022-10-06 10:31:21,297] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 500 100883
+[INFO] [2022-10-06 10:31:24,952] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[ERROR] [2022-10-06 10:31:24,995] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py", line 64, in get
+    for user in group.users:
+TypeError: 'ManyRelatedManager' object is not iterable
+[ERROR] [2022-10-06 10:31:24,995] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 500 101039
+[INFO] [2022-10-06 10:32:58,128] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:32:58,419] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:33:01,938] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[ERROR] [2022-10-06 10:33:02,042] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py", line 65, in get
+    for user in group.users:
+TypeError: 'ManyRelatedManager' object is not iterable
+[ERROR] [2022-10-06 10:33:02,043] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 500 101255
+[INFO] [2022-10-06 10:33:14,177] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:33:14,401] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:33:15,647] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[ERROR] [2022-10-06 10:33:15,726] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/group/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 511, in dispatch
+    self.response = self.finalize_response(request, response, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 423, in finalize_response
+    assert isinstance(response, HttpResponseBase), (
+AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'NoneType'>`
+[ERROR] [2022-10-06 10:33:15,726] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 500 81482
+[INFO] [2022-10-06 10:33:42,316] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:33:42,611] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:33:45,799] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:33:45,843] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 200 209
+[INFO] [2022-10-06 10:41:55,738] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:41:56,043] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:45:53,626] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 10:45:53,975] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:47:25,424] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 10:47:25,748] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:47:43,544] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/groupview.py changed, reloading.
+[INFO] [2022-10-06 10:47:43,832] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:50:15,710] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/group/views/grouplistview.py changed, reloading.
+[INFO] [2022-10-06 10:50:16,024] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[WARNING] [2022-10-06 10:51:05,849] [log.py:224] [log:log_response] - Method Not Allowed: /api/v1/group/TestLaboratory_V1_Group_2
+[WARNING] [2022-10-06 10:51:05,873] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/TestLaboratory_V1_Group_2 HTTP/1.1" 405 40
+[INFO] [2022-10-06 10:51:13,483] [basehttp.py:161] [basehttp:log_message] - "DELETE /api/v1/group/TestLaboratory_V1_Group_2 HTTP/1.1" 200 12
+[INFO] [2022-10-06 10:51:18,277] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:51:18,295] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 200 104
+[INFO] [2022-10-06 10:54:11,717] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group?code=762563 HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:54:11,751] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/?code=762563 HTTP/1.1" 200 104
+[INFO] [2022-10-06 10:54:13,380] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group?code=762563 HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:54:13,403] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/?code=762563 HTTP/1.1" 200 104
+[INFO] [2022-10-06 10:54:16,411] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group?code=76256 HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:54:16,422] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/?code=76256 HTTP/1.1" 200 2
+[INFO] [2022-10-06 10:54:19,944] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group?code=762563 HTTP/1.1" 301 0
+[INFO] [2022-10-06 10:54:19,966] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/?code=762563 HTTP/1.1" 200 104
+[INFO] [2022-10-06 10:59:11,305] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/urls.py changed, reloading.
+[INFO] [2022-10-06 10:59:11,636] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 10:59:39,798] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/urls.py changed, reloading.
+[INFO] [2022-10-06 10:59:40,088] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[WARNING] [2022-10-06 11:00:58,926] [log.py:224] [log:log_response] - Method Not Allowed: /api/v1/users/TestLaboratory_V1_User_2/join
+[WARNING] [2022-10-06 11:00:58,927] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/TestLaboratory_V1_User_2/join HTTP/1.1" 405 40
+[ERROR] [2022-10-06 11:01:02,832] [userjoinview.py:23] [userjoinview:post] - 分组不存在
+[ERROR] [2022-10-06 11:01:02,832] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_2/join
+[ERROR] [2022-10-06 11:01:02,833] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_2/join HTTP/1.1" 500 15
+[INFO] [2022-10-06 11:01:19,975] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_2/join HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:02:18,984] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/urls.py changed, reloading.
+[INFO] [2022-10-06 11:02:19,337] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:03:10,716] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/urls.py changed, reloading.
+[INFO] [2022-10-06 11:03:10,984] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[ERROR] [2022-10-06 11:04:00,849] [userjoinview.py:23] [userjoinview:post] - 分组不存在
+[ERROR] [2022-10-06 11:04:00,850] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_2/join
+[ERROR] [2022-10-06 11:04:00,851] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_2/join HTTP/1.1" 500 15
+[INFO] [2022-10-06 11:04:15,014] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_2/quit HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:06:24,370] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py changed, reloading.
+[INFO] [2022-10-06 11:06:24,737] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:06:37,390] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py changed, reloading.
+[INFO] [2022-10-06 11:06:37,596] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:07:18,652] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/ HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:08:30,640] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 200 296
+[ERROR] [2022-10-06 11:08:49,679] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py", line 75, in get
+    if user.group not in user_group_index.keys():
+AttributeError: 'User' object has no attribute 'group'
+[ERROR] [2022-10-06 11:08:49,680] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/%0A HTTP/1.1" 500 101050
+[INFO] [2022-10-06 11:11:17,096] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py changed, reloading.
+[INFO] [2022-10-06 11:11:17,417] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:11:30,623] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/%0A HTTP/1.1" 200 493
+[INFO] [2022-10-06 11:12:18,900] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/%0A HTTP/1.1" 200 495
+[INFO] [2022-10-06 11:19:37,421] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userlistview.py changed, reloading.
+[INFO] [2022-10-06 11:19:37,730] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:20:05,029] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/%0A HTTP/1.1" 200 515
+[INFO] [2022-10-06 11:22:38,128] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py changed, reloading.
+[INFO] [2022-10-06 11:22:38,457] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:23:01,401] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py changed, reloading.
+[INFO] [2022-10-06 11:23:01,675] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[INFO] [2022-10-06 11:25:03,778] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/ HTTP/1.1" 200 84
+[INFO] [2022-10-06 11:25:36,752] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/group/TestLaboratory_V1_Group_3/edit HTTP/1.1" 200 15
+[INFO] [2022-10-06 11:25:47,805] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group?code=596640 HTTP/1.1" 301 0
+[INFO] [2022-10-06 11:25:47,825] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/?code=596640 HTTP/1.1" 200 101
+[INFO] [2022-10-06 11:26:00,853] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_2/join HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:26:08,278] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[INFO] [2022-10-06 11:26:08,304] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 200 267
+[INFO] [2022-10-06 11:26:33,793] [basehttp.py:161] [basehttp:log_message] - "DELETE /api/v1/group/TestLaboratory_V1_Group_3 HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:26:37,691] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group HTTP/1.1" 301 0
+[INFO] [2022-10-06 11:26:37,712] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/group/ HTTP/1.1" 200 104
+[ERROR] [2022-10-06 11:26:58,747] [userlistview.py:38] [userlistview:post] - 用户名已存在,请修改用户名重新上传
+[ERROR] [2022-10-06 11:26:58,748] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/
+[ERROR] [2022-10-06 11:26:58,749] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/ HTTP/1.1" 500 51
+[INFO] [2022-10-06 11:27:04,845] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/ HTTP/1.1" 200 12
+[INFO] [2022-10-06 11:27:08,964] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 200 296
+[ERROR] [2022-10-06 11:27:29,246] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_5/edit
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+pymysql.err.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py", line 60, in post
+    user.save()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 726, in save
+    self.save_base(using=using, force_insert=force_insert,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 763, in save_base
+    updated = self._save_table(
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 845, in _save_table
+    updated = self._do_update(base_qs, using, pk_val, values, update_fields,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 899, in _do_update
+    return filtered._update(values) > 0
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/query.py", line 802, in _update
+    return query.get_compiler(self.db).execute_sql(CURSOR)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql
+    cursor = super().execute_sql(result_type)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
+    cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
+    return super().execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
+    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
+    return executor(sql, params, many, context)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
+    raise dj_exc_value.with_traceback(traceback) from exc_value
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+django.db.utils.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+[ERROR] [2022-10-06 11:27:29,256] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 500 248807
+[ERROR] [2022-10-06 11:27:32,414] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_5/edit
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+pymysql.err.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py", line 60, in post
+    user.save()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 726, in save
+    self.save_base(using=using, force_insert=force_insert,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 763, in save_base
+    updated = self._save_table(
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 845, in _save_table
+    updated = self._do_update(base_qs, using, pk_val, values, update_fields,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 899, in _do_update
+    return filtered._update(values) > 0
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/query.py", line 802, in _update
+    return query.get_compiler(self.db).execute_sql(CURSOR)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql
+    cursor = super().execute_sql(result_type)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
+    cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
+    return super().execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
+    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
+    return executor(sql, params, many, context)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
+    raise dj_exc_value.with_traceback(traceback) from exc_value
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+django.db.utils.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+[ERROR] [2022-10-06 11:27:32,477] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 500 248676
+[ERROR] [2022-10-06 11:28:12,635] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_5/edit
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+pymysql.err.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
+    response = get_response(request)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
+    response = wrapped_callback(request, *callback_args, **callback_kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/middleware/rolecontrol.py", line 48, in __call__
+    return self.func(request, *args, **kwargs)
+  File "/Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py", line 60, in post
+    user.save()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 726, in save
+    self.save_base(using=using, force_insert=force_insert,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 763, in save_base
+    updated = self._save_table(
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 845, in _save_table
+    updated = self._do_update(base_qs, using, pk_val, values, update_fields,
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/base.py", line 899, in _do_update
+    return filtered._update(values) > 0
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/query.py", line 802, in _update
+    return query.get_compiler(self.db).execute_sql(CURSOR)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql
+    cursor = super().execute_sql(result_type)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
+    cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
+    return super().execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
+    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
+    return executor(sql, params, many, context)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
+    raise dj_exc_value.with_traceback(traceback) from exc_value
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
+    return self.cursor.execute(sql, params)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 73, in execute
+    return self.cursor.execute(query, args)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 170, in execute
+    result = self._query(query)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/cursors.py", line 328, in _query
+    conn.query(q)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 516, in query
+    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 727, in _read_query_result
+    result.read()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 1066, in read
+    first_packet = self.connection._read_packet()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/connections.py", line 683, in _read_packet
+    packet.check_error()
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/protocol.py", line 220, in check_error
+    err.raise_mysql_exception(self._data)
+  File "/Users/liufan/program/software/python/miniforge3/lib/python3.9/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
+    raise errorclass(errno, errval)
+django.db.utils.IntegrityError: (1062, "Duplicate entry 'doctor' for key 'user.username'")
+[ERROR] [2022-10-06 11:28:12,644] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 500 248676
+[INFO] [2022-10-06 11:30:02,301] [autoreload.py:251] [autoreload:trigger_reload] - /Users/liufan/program/PYTHON/TestLaboratoryGit/TestLaboratory/apps/user/views/userview.py changed, reloading.
+[INFO] [2022-10-06 11:30:02,606] [autoreload.py:637] [autoreload:run_with_reloader] - Watching for file changes with StatReloader
+[ERROR] [2022-10-06 11:30:05,527] [userview.py:56] [userview:post] - 用户名已存在,请修改用户名
+[ERROR] [2022-10-06 11:30:05,528] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_5/edit
+[ERROR] [2022-10-06 11:30:05,528] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 500 39
+[INFO] [2022-10-06 11:30:12,244] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 200 15
+[INFO] [2022-10-06 11:30:31,858] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/TestLaboratory_V1_User_6 HTTP/1.1" 200 67
+[ERROR] [2022-10-06 11:31:17,763] [userlistview.py:94] [userlistview:post] - 用户名或密码错误
+[ERROR] [2022-10-06 11:31:17,764] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/login
+[ERROR] [2022-10-06 11:31:17,765] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 500 24
+[INFO] [2022-10-06 11:31:26,287] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/login HTTP/1.1" 200 307
+[INFO] [2022-10-06 11:31:29,886] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/%0A HTTP/1.1" 200 622
+[INFO] [2022-10-06 11:31:34,608] [basehttp.py:161] [basehttp:log_message] - "GET /api/v1/users/TestLaboratory_V1_User_6 HTTP/1.1" 200 67
+[ERROR] [2022-10-06 11:31:40,214] [userview.py:56] [userview:post] - 用户名已存在,请修改用户名
+[ERROR] [2022-10-06 11:31:40,215] [log.py:224] [log:log_response] - Internal Server Error: /api/v1/users/TestLaboratory_V1_User_5/edit
+[ERROR] [2022-10-06 11:31:40,215] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 500 39
+[INFO] [2022-10-06 11:31:44,583] [basehttp.py:161] [basehttp:log_message] - "POST /api/v1/users/TestLaboratory_V1_User_5/edit HTTP/1.1" 200 15

+ 0 - 0
logs/error-2022-10-04.log


+ 0 - 0
logs/error-2022-10-05.log


+ 0 - 0
logs/error-2022-10-06.log


+ 0 - 0
logs/info-2022-10-04.log


+ 0 - 0
logs/info-2022-10-05.log


+ 0 - 0
logs/info-2022-10-06.log


+ 102 - 41
mysql-init/TestLaboratory.sql

@@ -11,7 +11,7 @@
  Target Server Version : 80029
  File Encoding         : 65001
 
- Date: 20/06/2022 13:11:57
+ Date: 06/10/2022 11:36:52
 */
 
 SET NAMES utf8mb4;
@@ -67,7 +67,7 @@ CREATE TABLE `auth_permission` (
   PRIMARY KEY (`id`),
   UNIQUE KEY `auth_permission_content_type_id_codename_01ab375a_uniq` (`content_type_id`,`codename`),
   CONSTRAINT `auth_permission_content_type_id_2f476e4b_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of auth_permission
@@ -137,6 +137,10 @@ INSERT INTO `auth_permission` VALUES (61, 'Can add 日志', 16, 'add_log');
 INSERT INTO `auth_permission` VALUES (62, 'Can change 日志', 16, 'change_log');
 INSERT INTO `auth_permission` VALUES (63, 'Can delete 日志', 16, 'delete_log');
 INSERT INTO `auth_permission` VALUES (64, 'Can view 日志', 16, 'view_log');
+INSERT INTO `auth_permission` VALUES (65, 'Can add 被测试软件', 17, 'add_group');
+INSERT INTO `auth_permission` VALUES (66, 'Can change 被测试软件', 17, 'change_group');
+INSERT INTO `auth_permission` VALUES (67, 'Can delete 被测试软件', 17, 'delete_group');
+INSERT INTO `auth_permission` VALUES (68, 'Can view 被测试软件', 17, 'view_group');
 COMMIT;
 
 -- ----------------------------
@@ -244,7 +248,7 @@ CREATE TABLE `django_content_type` (
   `model` varchar(100) NOT NULL,
   PRIMARY KEY (`id`),
   UNIQUE KEY `django_content_type_app_label_model_76bd3d3b_uniq` (`app_label`,`model`)
-) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of django_content_type
@@ -256,6 +260,7 @@ INSERT INTO `django_content_type` VALUES (2, 'auth', 'permission');
 INSERT INTO `django_content_type` VALUES (4, 'auth', 'user');
 INSERT INTO `django_content_type` VALUES (5, 'contenttypes', 'contenttype');
 INSERT INTO `django_content_type` VALUES (15, 'file', 'filemanager');
+INSERT INTO `django_content_type` VALUES (17, 'group', 'group');
 INSERT INTO `django_content_type` VALUES (16, 'log', 'log');
 INSERT INTO `django_content_type` VALUES (12, 'plan', 'testplan');
 INSERT INTO `django_content_type` VALUES (6, 'sessions', 'session');
@@ -278,7 +283,7 @@ CREATE TABLE `django_migrations` (
   `name` varchar(255) NOT NULL,
   `applied` datetime(6) NOT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of django_migrations
@@ -314,6 +319,13 @@ INSERT INTO `django_migrations` VALUES (27, 'software', '0002_alter_software_nam
 INSERT INTO `django_migrations` VALUES (28, 'task', '0001_initial', '2022-06-19 10:44:32.893446');
 INSERT INTO `django_migrations` VALUES (29, 'task', '0002_alter_testtask_id', '2022-06-19 10:44:32.938279');
 INSERT INTO `django_migrations` VALUES (30, 'user', '0002_auto_20220619_1043', '2022-06-19 10:44:33.059425');
+INSERT INTO `django_migrations` VALUES (31, 'task', '0003_auto_20220626_1630', '2022-06-26 16:31:02.458212');
+INSERT INTO `django_migrations` VALUES (32, 'group', '0001_initial', '2022-10-04 20:49:38.358109');
+INSERT INTO `django_migrations` VALUES (33, 'software', '0003_auto_20221004_2044', '2022-10-04 20:49:38.476140');
+INSERT INTO `django_migrations` VALUES (34, 'task', '0004_alter_testcase_id', '2022-10-04 20:49:38.493060');
+INSERT INTO `django_migrations` VALUES (35, 'user', '0003_remove_user_group', '2022-10-05 17:30:42.091655');
+INSERT INTO `django_migrations` VALUES (36, 'group', '0002_group_users', '2022-10-05 17:30:42.127830');
+INSERT INTO `django_migrations` VALUES (37, 'group', '0003_alter_group_code', '2022-10-05 19:27:19.485913');
 COMMIT;
 
 -- ----------------------------
@@ -355,6 +367,48 @@ BEGIN;
 COMMIT;
 
 -- ----------------------------
+-- Table structure for group
+-- ----------------------------
+DROP TABLE IF EXISTS `group`;
+CREATE TABLE `group` (
+  `name` varchar(128) NOT NULL,
+  `id` varchar(128) NOT NULL,
+  `code` varchar(12) NOT NULL,
+  `manager` varchar(60) NOT NULL,
+  `create_time` datetime(6) NOT NULL,
+  `update_time` datetime(6) NOT NULL,
+  `delete` tinyint(1) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- ----------------------------
+-- Records of group
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for group_users
+-- ----------------------------
+DROP TABLE IF EXISTS `group_users`;
+CREATE TABLE `group_users` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `group_id` varchar(128) NOT NULL,
+  `user_id` varchar(128) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `group_users_group_id_user_id_c7ab77af_uniq` (`group_id`,`user_id`),
+  KEY `group_users_user_id_3c44daf2_fk_user_id` (`user_id`),
+  CONSTRAINT `group_users_group_id_3ffe8048_fk_group_id` FOREIGN KEY (`group_id`) REFERENCES `group` (`id`),
+  CONSTRAINT `group_users_user_id_3c44daf2_fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- ----------------------------
+-- Records of group_users
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
 -- Table structure for log
 -- ----------------------------
 DROP TABLE IF EXISTS `log`;
@@ -419,7 +473,14 @@ INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_25', '删除文
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_26', '查看用户', '/api/v1/users/.*', 'GET', '2021-07-17 17:18:35.000000', '2021-07-17 17:18:38.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_27', '编辑用户信息', '/api/v1/users/.*/edit', 'POST', '2021-07-15 11:22:54.000000', '2021-07-15 11:22:57.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_28', '查看版本列表', '/api/v1/software/versions', 'GET', '2021-07-20 17:32:29.000000', '2021-07-20 17:32:33.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_29', '创建分组', '/api/v1/group', 'POST', '2021-07-20 17:32:29.000000', '2021-07-20 17:32:33.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_3', '查看测试目标', '/api/v1/software/.*', 'GET', '2021-07-14 10:25:16.000000', '2021-07-14 10:25:19.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_30', '编辑分组信息', '/api/v1/group/.*/edit', 'POST', '2022-10-06 08:59:33.000000', '2022-10-06 08:59:38.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_31', '分组列表', '/api/v1/group', 'GET', '2022-10-06 09:00:25.000000', '2022-10-06 09:00:29.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_32', '查看分组信息', '/api/v1/group/.*', 'GET', '2022-10-06 09:01:18.000000', '2022-10-06 09:01:22.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_33', '删除分组', '/api/v1/group/.*', 'DELETE', '2022-10-06 09:01:59.000000', '2022-10-06 09:02:03.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_34', '加入班级', '/api/v1/users/.*/join', 'POST', '2022-10-06 09:02:48.000000', '2022-10-06 09:02:53.000000', 0);
+INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_35', '退出班级', '/api/v1/users/.*/quit', 'POST', '2022-10-06 09:03:27.000000', '2022-10-06 09:03:30.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_4', '编辑测试目标', '/api/v1/software/.*/edit', 'POST', '2021-07-14 10:25:48.000000', '2021-07-14 10:25:50.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_5', '删除测试目标', '/api/v1/software/.*', 'DELETE', '2021-07-14 10:26:40.000000', '2021-07-14 10:26:42.000000', 0);
 INSERT INTO `permission` VALUES ('TestLaboratory_V1_Permission_6', '生成测试报告', '/api/v1/software/.*/report', 'GET', '2021-07-14 10:27:43.000000', '2021-07-14 10:27:46.000000', 0);
@@ -443,12 +504,12 @@ CREATE TABLE `plan` (
   `update_time` datetime(6) NOT NULL,
   `delete` tinyint(1) NOT NULL,
   `creator_id` varchar(128) DEFAULT NULL,
-  `software_id` varchar(30) NOT NULL,
+  `software_id` varchar(128) NOT NULL,
   PRIMARY KEY (`id`),
-  KEY `plan_software_id_4b28cc2e_fk_software_id` (`software_id`),
   KEY `plan_creator_id_c94ecd21_fk` (`creator_id`),
+  KEY `plan_software_id_4b28cc2e_fk` (`software_id`),
   CONSTRAINT `plan_creator_id_c94ecd21_fk` FOREIGN KEY (`creator_id`) REFERENCES `user` (`id`),
-  CONSTRAINT `plan_software_id_4b28cc2e_fk_software_id` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`)
+  CONSTRAINT `plan_software_id_4b28cc2e_fk` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
@@ -491,7 +552,7 @@ CREATE TABLE `role_permissions` (
   PRIMARY KEY (`id`),
   UNIQUE KEY `role_permissions_role_id_permission_id_04f77df0_uniq` (`role_id`,`permission_id`),
   KEY `role_permissions_permission_id_ad343843_fk_permission_id` (`permission_id`)
-) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of role_permissions
@@ -517,7 +578,14 @@ INSERT INTO `role_permissions` VALUES (56, 'TestLaboratory_V1_Role_1', 'TestLabo
 INSERT INTO `role_permissions` VALUES (58, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_26');
 INSERT INTO `role_permissions` VALUES (61, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_27');
 INSERT INTO `role_permissions` VALUES (65, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_28');
+INSERT INTO `role_permissions` VALUES (67, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_29');
 INSERT INTO `role_permissions` VALUES (3, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_3');
+INSERT INTO `role_permissions` VALUES (69, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_30');
+INSERT INTO `role_permissions` VALUES (71, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_31');
+INSERT INTO `role_permissions` VALUES (73, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_32');
+INSERT INTO `role_permissions` VALUES (75, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_33');
+INSERT INTO `role_permissions` VALUES (77, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_34');
+INSERT INTO `role_permissions` VALUES (80, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_35');
 INSERT INTO `role_permissions` VALUES (4, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_4');
 INSERT INTO `role_permissions` VALUES (5, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_5');
 INSERT INTO `role_permissions` VALUES (6, 'TestLaboratory_V1_Role_1', 'TestLaboratory_V1_Permission_6');
@@ -544,7 +612,14 @@ INSERT INTO `role_permissions` VALUES (57, 'TestLaboratory_V1_Role_2', 'TestLabo
 INSERT INTO `role_permissions` VALUES (59, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_26');
 INSERT INTO `role_permissions` VALUES (62, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_27');
 INSERT INTO `role_permissions` VALUES (66, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_28');
+INSERT INTO `role_permissions` VALUES (68, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_29');
 INSERT INTO `role_permissions` VALUES (24, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_3');
+INSERT INTO `role_permissions` VALUES (70, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_30');
+INSERT INTO `role_permissions` VALUES (72, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_31');
+INSERT INTO `role_permissions` VALUES (74, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_32');
+INSERT INTO `role_permissions` VALUES (76, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_33');
+INSERT INTO `role_permissions` VALUES (78, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_34');
+INSERT INTO `role_permissions` VALUES (81, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_35');
 INSERT INTO `role_permissions` VALUES (25, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_4');
 INSERT INTO `role_permissions` VALUES (26, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_5');
 INSERT INTO `role_permissions` VALUES (27, 'TestLaboratory_V1_Role_2', 'TestLaboratory_V1_Permission_6');
@@ -563,6 +638,8 @@ INSERT INTO `role_permissions` VALUES (53, 'TestLaboratory_V1_Role_3', 'TestLabo
 INSERT INTO `role_permissions` VALUES (60, 'TestLaboratory_V1_Role_3', 'TestLaboratory_V1_Permission_26');
 INSERT INTO `role_permissions` VALUES (63, 'TestLaboratory_V1_Role_3', 'TestLaboratory_V1_Permission_27');
 INSERT INTO `role_permissions` VALUES (44, 'TestLaboratory_V1_Role_3', 'TestLaboratory_V1_Permission_3');
+INSERT INTO `role_permissions` VALUES (79, 'TestLaboratory_V1_Role_3', 'TestLaboratory_V1_Permission_34');
+INSERT INTO `role_permissions` VALUES (82, 'TestLaboratory_V1_Role_3', 'TestLaboratory_V1_Permission_35');
 COMMIT;
 
 -- ----------------------------
@@ -571,7 +648,7 @@ COMMIT;
 DROP TABLE IF EXISTS `software`;
 CREATE TABLE `software` (
   `name` varchar(128) NOT NULL,
-  `id` varchar(30) NOT NULL,
+  `id` varchar(128) NOT NULL,
   `type` varchar(20) NOT NULL,
   `report_file` longtext,
   `create_time` datetime(6) NOT NULL,
@@ -584,7 +661,6 @@ CREATE TABLE `software` (
 -- Records of software
 -- ----------------------------
 BEGIN;
-INSERT INTO `software` VALUES ('test1', 'TestLaboratory_V1_Software_1', '功能测试', NULL, '1900-01-20 15:25:09.000000', '1900-01-20 15:25:09.000000', 0);
 COMMIT;
 
 -- ----------------------------
@@ -606,8 +682,11 @@ CREATE TABLE `task` (
   `update_time` datetime(6) NOT NULL,
   `delete` tinyint(1) NOT NULL,
   `plan_id` varchar(128) NOT NULL,
+  `executor_id` varchar(128) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `task_plan_id_77395325_fk_plan_id` (`plan_id`),
+  KEY `task_executor_id_24a67329_fk_user_id` (`executor_id`),
+  CONSTRAINT `task_executor_id_24a67329_fk_user_id` FOREIGN KEY (`executor_id`) REFERENCES `user` (`id`),
   CONSTRAINT `task_plan_id_77395325_fk_plan_id` FOREIGN KEY (`plan_id`) REFERENCES `plan` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
@@ -618,30 +697,11 @@ BEGIN;
 COMMIT;
 
 -- ----------------------------
--- Table structure for task_executor
--- ----------------------------
-DROP TABLE IF EXISTS `task_executor`;
-CREATE TABLE `task_executor` (
-  `id` bigint NOT NULL AUTO_INCREMENT,
-  `testtask_id` varchar(128) NOT NULL,
-  `user_id` varchar(128) NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `task_executor_testtask_id_user_id_33019daf_uniq` (`testtask_id`,`user_id`),
-  KEY `task_executor_user_id_0f117fee_fk_user_id` (`user_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-
--- ----------------------------
--- Records of task_executor
--- ----------------------------
-BEGIN;
-COMMIT;
-
--- ----------------------------
 -- Table structure for test_case
 -- ----------------------------
 DROP TABLE IF EXISTS `test_case`;
 CREATE TABLE `test_case` (
-  `id` varchar(30) NOT NULL,
+  `id` varchar(128) NOT NULL,
   `id_in_task` varchar(30) NOT NULL,
   `version` varchar(30) DEFAULT NULL,
   `name` varchar(50) NOT NULL,
@@ -660,12 +720,15 @@ CREATE TABLE `test_case` (
   `update_time` datetime(6) NOT NULL,
   `delete` tinyint(1) NOT NULL,
   `remark` longtext,
-  `software_id` varchar(30) DEFAULT NULL,
+  `software_id` varchar(128) DEFAULT NULL,
   `task_id` varchar(128) NOT NULL,
+  `executor_id_id` varchar(128) DEFAULT NULL,
   PRIMARY KEY (`id`),
-  KEY `test_case_software_id_b7e9af75_fk_software_id` (`software_id`),
   KEY `test_case_task_id_6c501356_fk` (`task_id`),
-  CONSTRAINT `test_case_software_id_b7e9af75_fk_software_id` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`),
+  KEY `test_case_executor_id_id_4afa1b6e_fk_user_id` (`executor_id_id`),
+  KEY `test_case_software_id_b7e9af75_fk` (`software_id`),
+  CONSTRAINT `test_case_executor_id_id_4afa1b6e_fk_user_id` FOREIGN KEY (`executor_id_id`) REFERENCES `user` (`id`),
+  CONSTRAINT `test_case_software_id_b7e9af75_fk` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`),
   CONSTRAINT `test_case_task_id_6c501356_fk` FOREIGN KEY (`task_id`) REFERENCES `task` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
@@ -690,7 +753,6 @@ CREATE TABLE `user` (
   `update_time` datetime(6) NOT NULL,
   `is_login` tinyint(1) NOT NULL,
   `delete` tinyint(1) NOT NULL,
-  `group` varchar(128) NOT NULL,
   PRIMARY KEY (`id`),
   UNIQUE KEY `username` (`username`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
@@ -699,10 +761,9 @@ CREATE TABLE `user` (
 -- Records of user
 -- ----------------------------
 BEGIN;
-INSERT INTO `user` VALUES ('TestLaboratory_V1_User_1', 'honghong', '小红', '123456', '18851111391', 1, '2021-07-13 14:23:25.000000', '2022-06-19 12:19:23.861094', 1, 0, '默认分组');
-INSERT INTO `user` VALUES ('TestLaboratory_V1_User_2', 'zxc', '小蓝', '123456', '11223344556', 2, '2021-09-26 15:41:37.000000', '1900-01-20 17:33:18.000000', 1, 0, '默认分组');
-INSERT INTO `user` VALUES ('TestLaboratory_V1_User_3', 'bcd', '小黄', '123456', '138138138138', 2, '2021-09-26 15:44:39.000000', '2021-09-26 15:44:43.000000', 0, 0, '默认分组');
-INSERT INTO `user` VALUES ('TestLaboratory_V1_User_4', 'doctor', '医生', '12345', '13888', 1, '2022-06-19 11:21:02.296993', '2022-06-20 12:17:07.818682', 1, 0, '教室');
+INSERT INTO `user` VALUES ('TestLaboratory_V1_User_1', 'honghong', '小红', '123456', '18851111391', 1, '2021-07-13 14:23:25.000000', '2022-10-05 19:43:42.066458', 1, 0);
+INSERT INTO `user` VALUES ('TestLaboratory_V1_User_2', 'zxc', '小蓝', '123456', '11223344556', 2, '2021-09-26 15:41:37.000000', '1900-01-20 17:33:18.000000', 0, 0);
+INSERT INTO `user` VALUES ('TestLaboratory_V1_User_3', 'bcd', '小黄', '123456', '138138138138', 2, '2021-09-26 15:44:39.000000', '2021-09-26 15:44:43.000000', 0, 0);
 COMMIT;
 
 -- ----------------------------
@@ -729,16 +790,16 @@ COMMIT;
 -- ----------------------------
 DROP TABLE IF EXISTS `version`;
 CREATE TABLE `version` (
-  `id` varchar(30) NOT NULL,
+  `id` varchar(128) NOT NULL,
   `number` varchar(20) NOT NULL,
   `version_file` longtext NOT NULL,
   `create_time` datetime(6) NOT NULL,
   `update_time` datetime(6) NOT NULL,
   `delete` tinyint(1) NOT NULL,
-  `software_id` varchar(30) NOT NULL,
+  `software_id` varchar(128) NOT NULL,
   PRIMARY KEY (`id`),
   KEY `version_software_id_d30b116d` (`software_id`),
-  CONSTRAINT `version_software_id_d30b116d_fk_software_id` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`)
+  CONSTRAINT `version_software_id_d30b116d_fk` FOREIGN KEY (`software_id`) REFERENCES `software` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------

+ 89 - 0
utils/util_random.py

@@ -0,0 +1,89 @@
+class Produce:
+    # 定义一个空列表,是随机数来源的容器
+    __rand_num = list()
+
+    # 定义一个空集合,用于存储已经产生的验证码,(也可以用空列表)
+    __abandon = set()
+
+    # 验证码容器
+    @classmethod
+    def __vessel(cls, option='num or letter'):
+
+        # 清空列表,(随机数来源的容器)
+        cls.__rand_num = list()
+
+        if option == 'num':
+            # 把数字存入列表
+            for i in range(10):
+                cls.__rand_num.append(str(i))
+
+        elif option == 'letter':
+            # 把大小写字母存入列表
+            for i in range(26):
+                cls.__rand_num.append(chr(i + 65))  # 大写字母
+                cls.__rand_num.append(chr(i + 97))  # 小写字母
+
+        elif option == 'num or letter':
+            # 把数字存入列表
+            for i in range(10):
+                cls.__rand_num.append(str(i))
+
+            # 把大小写字母存入列表
+            for i in range(26):
+                cls.__rand_num.append(chr(i + 65))  # 大写字母
+                cls.__rand_num.append(chr(i + 97))  # 小写字母
+
+        else:
+            print('参数option传递错误!!!')
+            print("option='num' or 'letter'")
+
+            import sys
+            sys.exit()
+
+    # 随机生成6位验证码
+    @classmethod
+    def auth_code(cls, option='num or letter', num=6):
+
+        buf = ''  # 定义一个空的字符串,用于存储6位验证码
+
+        cls.__vessel(option=option)  # 验证码容器
+
+        from random import choice  # 导入随机模块
+
+        for i in range(num):
+            buf += choice(cls.__rand_num)  # 随机数拼接成6位验证码
+
+        # 如果废弃站集合为空
+        if cls.__abandon == set():
+            cls.__abandon.add(buf)  # 把验证码存入废弃站集合,说明此验证码不能再使用
+            return buf
+
+        # 保证6位验证码不重复
+        for i in cls.__abandon:
+
+            # 如果验证码重复
+            if buf == i:
+                buf = cls.auth_code(option=option, num=num)
+                return buf
+
+        # 验证码不重复
+        cls.__abandon.add(buf)  # 把验证码存入废弃站集合,说明此验证码不能再使用
+        return buf
+
+    # 查看数据
+    @classmethod
+    def check_data(cls):
+        print(f'随机数库:{cls.__rand_num}')
+        print('废弃站:{}'.format(cls.__abandon))
+
+    # 清空废弃站
+    @classmethod
+    def clear_abandon(cls):
+        cls.__abandon.clear()
+
+
+# 程序测试
+if __name__ == '__main__':
+    for i in range(100):
+        num = Produce.auth_code(option='num')
+        print(Produce.auth_code(option='num'))