├── db.sqlite3 ├── app ├── __init__.py ├── migrations │ └── __init__.py ├── models.py ├── admin.py ├── tests.py ├── apps.py └── views.py ├── .gitignore ├── student_info ├── __init__.py ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── static ├── images │ └── loading.gif └── js │ └── jquery-3.5.1.min.js ├── templates ├── add_class.html ├── edit_class.html ├── add_student.html ├── add_teacher.html ├── edit_teacher.html ├── edit_student.html ├── login.html ├── layout.html ├── teacher.html ├── class.html └── student.html ├── manage.py ├── README.md ├── utils └── sqlhelper.py └── test.sql /db.sqlite3: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /app/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /student_info/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /app/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /app/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AppConfig(AppConfig): 5 | name = 'app' 6 | -------------------------------------------------------------------------------- /static/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThanlonSmith/stu-django/HEAD/static/images/loading.gif -------------------------------------------------------------------------------- /student_info/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for student_info project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'student_info.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /student_info/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for student_info project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'student_info.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /templates/add_class.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 | 11 | 12 | 13 |
14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /templates/edit_class.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 | 11 | {# #} 12 | 13 | 14 |
15 |
16 | {% endblock %} -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'student_info.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | django实现学生信息管理系统,学生信息管理系统是针对学校人事处的大量业务处理工作而开发的管理软件,主要用于学校学生信息管理,总体任务是实现学生信息关系的系统化、科学化、规范化和自动化,其主要任务是用计算机对学生各种信息进行日常管理,如查询、修改、增加、删除,另外还考虑到学生选课,针对这些要求设计了学生信息管理系统。 2 | ##### 1. 数据库表的结构设计 3 | ##### 2. 后台引入母板 4 | ##### 3. 查询班级信息 5 | ##### 4. 添加班级信息 6 | ##### 5. 编辑班级信息 7 | ##### 6. 删除班级信息 8 | ##### 7. 查询学生信息 9 | ##### 8. 添加学生信息 10 | ##### 9. 编辑学生信息 11 | ##### 10. 删除学生信息 12 | ##### 11. Bootstrap介绍 13 | ##### 12. AJAX添加班级信息 14 | ##### 13. AJAX编辑班级信息 15 | ##### 14. AJAX删除班级信息 16 | ##### 15. 数据库操作代码复用 17 | ##### 16. AJAX添加学生信息 18 | ##### 17. AJAX编辑学生信息 19 | ##### 18. AJAX删除学生信息 20 | ##### 19. 分页展示学生表 21 | ##### 20. 数据库操作封装 22 | ##### 21. 添加教师信息 23 | ##### 22. 查询教师和任课班级信息 24 | ##### 23. 编辑教师信息 25 | ##### 24. AJAX删除教师信息 26 | ##### 25. AJAX添加教师信息 27 | -------------------------------------------------------------------------------- /templates/add_student.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 |
11 |
{#如果没有写,默热提交到当前url#} 12 |
13 | 14 | 15 |
16 |
17 | 22 |
23 | 24 |
25 |
26 |
27 |
28 | {% endblock %} -------------------------------------------------------------------------------- /templates/add_teacher.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 |
11 |
12 |
13 | 14 | 15 |
16 |
17 | 22 |
23 | 24 |
25 |
26 |
27 |
28 | {% endblock %} -------------------------------------------------------------------------------- /templates/edit_teacher.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 |
11 |
12 |
13 | 14 | 16 |
17 |
18 | 27 |
28 | 29 |
30 |
31 |
32 |
33 | {% endblock %} -------------------------------------------------------------------------------- /templates/edit_student.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %}{% endblock %} 3 | {% block content %} 4 | 8 |
9 |
10 |
11 |
12 | {# 还可以设置input标签将其隐藏#} 13 |
14 | 15 | 17 |
18 |
19 | 28 |
29 | 30 |
31 |
32 |
33 |
34 | {% endblock %} -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 学生信息管理系统登录 9 | 13 | 14 | 15 |
16 |
17 |
18 |
19 |

学生信息管理系统登录

20 |
21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 | 31 |
32 |
33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /student_info/urls.py: -------------------------------------------------------------------------------- 1 | """student_info URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from app import views 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('user/login/', views.login), 23 | path('user/class/', views.classes), 24 | path('user/add_class/', views.add_class), 25 | path('user/edit_class/', views.edit_class), 26 | path('user/del_class/', views.del_class), 27 | path('user/student/', views.student, name='student'), 28 | path('user/add_student/', views.add_student), 29 | path('user/edit_student/', views.edit_student), 30 | path('user/del_student/', views.del_student), 31 | path('user/add_class_modal/', views.add_class_modal), 32 | path('user/edit_class_modal/', views.edit_class_modal), 33 | path('user/del_class_modal/', views.del_class_modal), 34 | path('user/add_student_modal/', views.add_student_modal), 35 | path('user/edit_student_modal/', views.edit_student_modal), 36 | path('user/del_student_modal/', views.del_student_modal), 37 | path('user/teacher/', views.teacher), 38 | path('user/add_teacher/', views.add_teacher), 39 | path('user/edit_teacher/', views.edit_teacher), 40 | path('user/add_teacher_modal/', views.add_teacher_modal), 41 | path('user/del_teacher_modal/', views.del_teacher_modal), 42 | ] 43 | -------------------------------------------------------------------------------- /utils/sqlhelper.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | 3 | 4 | def get_list(sql, args): 5 | """ 6 | 返回查询到的所有结果 7 | :param sql: 8 | :param args: 9 | :return: 10 | """ 11 | # 创建连接 12 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8') 13 | # 创建游标 14 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 15 | # 执行sql 16 | cursor.execute(sql, args) 17 | # 获取查询到的内容 18 | ret = cursor.fetchall() 19 | # 关闭游标 20 | cursor.close() 21 | # 关闭连接 22 | conn.close() 23 | return ret 24 | 25 | 26 | def get_one(sql, args): 27 | """ 28 | 返回查询到的一条结果 29 | :param sql: 30 | :param args: 31 | :return: 32 | """ 33 | # 创建连接 34 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8') 35 | # 创建游标 36 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 37 | # 执行sql 38 | cursor.execute(sql, args) 39 | # 获取查询到的内容 40 | ret = cursor.fetchone() 41 | # 关闭游标 42 | cursor.close() 43 | # 关闭连接 44 | conn.close() 45 | return ret 46 | 47 | 48 | def modify(sql, args): 49 | """ 50 | 修改和删除操作 51 | :param sql: 52 | :param args: 53 | :return: 54 | """ 55 | # 创建连接 56 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8') 57 | # 创建游标 58 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 59 | # 执行sql 60 | cursor.execute(sql, args) 61 | # 提交事务 62 | conn.commit() 63 | # 关闭游标 64 | cursor.close() 65 | # 关闭连接 66 | conn.close() 67 | 68 | 69 | class SqlHelper: 70 | def __init__(self): 71 | self.conn() 72 | 73 | def conn(self): 74 | self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', 75 | charset='utf8') 76 | self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) 77 | 78 | def get_list(self, sql, args): 79 | self.cursor.execute(sql, args) 80 | result = self.cursor.fetchall() 81 | return result 82 | 83 | def get_one(self, sql, args): 84 | self.cursor.execute(sql, args) 85 | result = self.cursor.fetchone() 86 | return result 87 | 88 | def modify(self, sql, args): 89 | self.cursor.execute(sql, args) 90 | self.conn.commit() 91 | 92 | def multiple_modify(self, sql, args): 93 | self.cursor.executemany(sql, args) 94 | self.conn.commit() 95 | 96 | def create(self, sql, args): 97 | self.cursor.execute(sql, args) 98 | self.conn.commit() 99 | return self.cursor.lastrowid 100 | 101 | def close(self): 102 | self.cursor.close() 103 | self.conn.close() 104 | -------------------------------------------------------------------------------- /student_info/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for student_info project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.6. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | # Quick-start development settings - unsuitable for production 19 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 20 | 21 | # SECURITY WARNING: keep the secret key used in production secret! 22 | SECRET_KEY = 'dri+*icl2+p!lz3zg4$!_d%*igd%)cl2bd85z+c12v1(ekb6b3' 23 | 24 | # SECURITY WARNING: don't run with debug turned on in production! 25 | DEBUG = True 26 | 27 | ALLOWED_HOSTS = [] 28 | 29 | # Application definition 30 | 31 | INSTALLED_APPS = [ 32 | 'django.contrib.admin', 33 | 'django.contrib.auth', 34 | 'django.contrib.contenttypes', 35 | 'django.contrib.sessions', 36 | 'django.contrib.messages', 37 | 'django.contrib.staticfiles', 38 | 'app.apps.AppConfig', 39 | ] 40 | 41 | MIDDLEWARE = [ 42 | 'django.middleware.security.SecurityMiddleware', 43 | 'django.contrib.sessions.middleware.SessionMiddleware', 44 | 'django.middleware.common.CommonMiddleware', 45 | # 'django.middleware.csrf.CsrfViewMiddleware', 46 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 47 | 'django.contrib.messages.middleware.MessageMiddleware', 48 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 49 | ] 50 | 51 | ROOT_URLCONF = 'student_info.urls' 52 | 53 | TEMPLATES = [ 54 | { 55 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 56 | 'DIRS': [os.path.join(BASE_DIR, 'templates')] 57 | , 58 | 'APP_DIRS': True, 59 | 'OPTIONS': { 60 | 'context_processors': [ 61 | 'django.template.context_processors.debug', 62 | 'django.template.context_processors.request', 63 | 'django.contrib.auth.context_processors.auth', 64 | 'django.contrib.messages.context_processors.messages', 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = 'student_info.wsgi.application' 71 | 72 | # Database 73 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 74 | 75 | DATABASES = { 76 | 'default': { 77 | 'ENGINE': 'django.db.backends.sqlite3', 78 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 79 | } 80 | } 81 | 82 | # Password validation 83 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 84 | 85 | AUTH_PASSWORD_VALIDATORS = [ 86 | { 87 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 88 | }, 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 97 | }, 98 | ] 99 | 100 | # Internationalization 101 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 102 | 103 | LANGUAGE_CODE = 'en-us' 104 | 105 | TIME_ZONE = 'UTC' 106 | 107 | USE_I18N = True 108 | 109 | USE_L10N = True 110 | 111 | USE_TZ = True 112 | 113 | # Static files (CSS, JavaScript, Images) 114 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 115 | 116 | STATIC_URL = '/static/' 117 | STATICFILES_DIRS = ( 118 | os.path.join(BASE_DIR, 'static'), 119 | ) 120 | -------------------------------------------------------------------------------- /templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 后台管理 9 | 11 | 45 | {% block css %}{% endblock %} 46 | 47 | 48 |
49 |
50 |

学生信息管理系统

51 |
52 |
53 | 55 |
56 | 60 |
61 |
62 |
邮件 65 |
66 |
消息 69 |
70 |
71 |
72 |
73 | 81 |
82 |
83 | {% block content %} 84 | {% endblock %} 85 |
86 | 87 | 88 | 91 | {% block js %}{% endblock %} 92 | -------------------------------------------------------------------------------- /test.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.20, for Linux (x86_64) 2 | -- 3 | -- Host: localhost Database: test 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.20-0ubuntu0.20.04.1 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `class` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `class`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `class` ( 26 | `id` int NOT NULL AUTO_INCREMENT, 27 | `title` varchar(20) NOT NULL, 28 | PRIMARY KEY (`id`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; 30 | /*!40101 SET character_set_client = @saved_cs_client */; 31 | 32 | -- 33 | -- Dumping data for table `class` 34 | -- 35 | 36 | LOCK TABLES `class` WRITE; 37 | /*!40000 ALTER TABLE `class` DISABLE KEYS */; 38 | INSERT INTO `class` VALUES (1,'软件工程'),(8,'软件技术'),(9,'计算机科学与技术'),(10,'网络工程'); 39 | /*!40000 ALTER TABLE `class` ENABLE KEYS */; 40 | UNLOCK TABLES; 41 | 42 | -- 43 | -- Table structure for table `student` 44 | -- 45 | 46 | DROP TABLE IF EXISTS `student`; 47 | /*!40101 SET @saved_cs_client = @@character_set_client */; 48 | /*!50503 SET character_set_client = utf8mb4 */; 49 | CREATE TABLE `student` ( 50 | `id` int NOT NULL AUTO_INCREMENT, 51 | `name` varchar(10) NOT NULL, 52 | `class_id` int NOT NULL, 53 | PRIMARY KEY (`id`) 54 | ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8; 55 | /*!40101 SET character_set_client = @saved_cs_client */; 56 | 57 | -- 58 | -- Dumping data for table `student` 59 | -- 60 | 61 | LOCK TABLES `student` WRITE; 62 | /*!40000 ALTER TABLE `student` DISABLE KEYS */; 63 | INSERT INTO `student` VALUES (17,'超越',9),(18,'奈何',9),(19,'2323',10),(20,'2323',1); 64 | /*!40000 ALTER TABLE `student` ENABLE KEYS */; 65 | UNLOCK TABLES; 66 | 67 | -- 68 | -- Table structure for table `teacher` 69 | -- 70 | 71 | DROP TABLE IF EXISTS `teacher`; 72 | /*!40101 SET @saved_cs_client = @@character_set_client */; 73 | /*!50503 SET character_set_client = utf8mb4 */; 74 | CREATE TABLE `teacher` ( 75 | `id` int NOT NULL AUTO_INCREMENT, 76 | `name` varchar(10) NOT NULL, 77 | PRIMARY KEY (`id`) 78 | ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8; 79 | /*!40101 SET character_set_client = @saved_cs_client */; 80 | 81 | -- 82 | -- Dumping data for table `teacher` 83 | -- 84 | 85 | LOCK TABLES `teacher` WRITE; 86 | /*!40000 ALTER TABLE `teacher` DISABLE KEYS */; 87 | INSERT INTO `teacher` VALUES (1,'李娇'),(2,'李晓'); 88 | /*!40000 ALTER TABLE `teacher` ENABLE KEYS */; 89 | UNLOCK TABLES; 90 | 91 | -- 92 | -- Table structure for table `teacher2class` 93 | -- 94 | 95 | DROP TABLE IF EXISTS `teacher2class`; 96 | /*!40101 SET @saved_cs_client = @@character_set_client */; 97 | /*!50503 SET character_set_client = utf8mb4 */; 98 | CREATE TABLE `teacher2class` ( 99 | `id` int NOT NULL AUTO_INCREMENT, 100 | `teacher_id` int NOT NULL, 101 | `class_id` int NOT NULL, 102 | PRIMARY KEY (`id`) 103 | ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8; 104 | /*!40101 SET character_set_client = @saved_cs_client */; 105 | 106 | -- 107 | -- Dumping data for table `teacher2class` 108 | -- 109 | 110 | LOCK TABLES `teacher2class` WRITE; 111 | /*!40000 ALTER TABLE `teacher2class` DISABLE KEYS */; 112 | INSERT INTO `teacher2class` VALUES (1,1,1),(2,1,8),(3,1,9),(4,1,10),(14,2,1),(15,2,9),(16,2,10); 113 | /*!40000 ALTER TABLE `teacher2class` ENABLE KEYS */; 114 | UNLOCK TABLES; 115 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 116 | 117 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 118 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 119 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 120 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 121 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 122 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 123 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 124 | 125 | -- Dump completed on 2020-06-13 22:06:33 126 | -------------------------------------------------------------------------------- /templates/teacher.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %} 3 | 39 | {% endblock %} 40 | {% block content %} 41 | 44 |
45 | 添加(1) 46 | 添加(2) 48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {% for row in teacher_list %} 58 | 59 | 60 | 61 | 66 | 70 | 71 | {% endfor %} 72 |
ID教师姓名任教班级操作
{{ row.tid }}{{ row.name }} 62 | {% for item in row.titles %} 63 | {{ item }} 64 | {% endfor %} 65 | 67 | 编辑 68 | 删除 69 |
73 | 74 | 101 | 102 |
103 | {% endblock %} 104 | {% block js %} 105 | 193 | {% endblock %} -------------------------------------------------------------------------------- /templates/class.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html' %} 2 | {% block css %} 3 | 27 | {% endblock %} 28 | {% block content %} 29 | 33 |
34 | 添加(1) 35 | 添加(2) 36 |
37 | 38 | 57 | 58 | 59 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | {% for row in class_list %} 87 | 88 | 89 | 90 | 98 | 99 | {% endfor %} 100 |
id班级名称操作
{{ row.id }}{{ row.title }} 91 | 编辑(1) 93 | 编辑(2) 95 | 删除(1) 96 | 删除(2) 97 |
101 | 102 | {# #} 121 |
122 | {% endblock %} 123 | {% block js %} 124 | 210 | {% endblock %} -------------------------------------------------------------------------------- /templates/student.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block css %} 3 | 27 | {% endblock %} 28 | {% block content %} 29 | 33 |
34 | 添加(1) 35 | 添加(2) 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {% for row in posts.object_list %} 47 | 48 | 49 | 50 | 51 | {# #} 52 | 58 | 59 | {% endfor %} 60 |
ID学生姓名学生班级操作
{{ row.id }}{{ row.name }}{{ row.title }}{{ row.class_id }} 53 | 编辑(1) 54 | 编辑(2) 55 | 删除(1) 56 | 删除(2) 57 |
61 | 62 | 78 | 79 | 80 | 107 | 108 | 109 | 136 | 137 |
138 | {% endblock %} 139 | {% block js %} 140 | 238 | {% endblock %} -------------------------------------------------------------------------------- /app/views.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | from django.shortcuts import render, redirect, HttpResponse 3 | from utils import sqlhelper 4 | import json 5 | from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage 6 | 7 | 8 | # Create your views here. 9 | def login(request): 10 | ''' 11 | 用户登录 12 | :param request: 13 | :return: 14 | ''' 15 | username = request.POST.get('username') 16 | pwd = request.POST.get('pwd') 17 | if request.method == 'POST': 18 | if username == 'thanlon' and pwd == '123456': 19 | obj = redirect('/user/class/') 20 | obj.set_signed_cookie('ticket', 'thanlon', salt='123456') 21 | return obj 22 | else: 23 | return render(request, 'login.html') 24 | 25 | 26 | def classes(request): 27 | """ 28 | 查询班级信息 29 | :param request: 30 | :return: 31 | """ 32 | ticket = request.get_signed_cookie('ticket', salt='123456') 33 | if not ticket: 34 | return redirect('/login/') 35 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 36 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 37 | cursor.execute("select id,title from class") 38 | class_list = cursor.fetchall() 39 | # print(class_list) 40 | # [{'id': 1, 'title': '软件工程'}, {'id': 3, 'title': '网络工程'}, {'id': 4, 'title': '计算机科学与技术'}] 41 | cursor.close() 42 | conn.close() 43 | return render(request, 'class.html', {'class_list': class_list}) 44 | 45 | 46 | def add_class(request): 47 | """ 48 | 添加班级信息 49 | :param request: 50 | :return: 51 | """ 52 | # 如果是get请求就返回add_class.html模板就可以 53 | if request.method == 'GET': 54 | return render(request, 'add_class.html') 55 | # 如果是post请求则执行下面的代码 56 | else: 57 | # 获取班级的标题 58 | class_title = request.POST.get('class_title') 59 | print(class_title) 60 | # 创建数据库连接对象 61 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 62 | # 创建游标 63 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 64 | # 将班级的名称传到sql语句中 65 | cursor.execute('insert into class(title) values(%s)', class_title) 66 | # cursor.execute("insert into class(title) values(%s)", [class_title, ]) 67 | # 提交(查询不需要,其它如添加、修改、更新数据是需要执行commit方法才能将数据插入成功) 68 | conn.commit() 69 | # 关闭游标 70 | cursor.close() 71 | # 关闭连接 72 | conn.close() 73 | # 添加之后就会重定向到/classes/路由,会显示添加后的班级 74 | return redirect('/user/class/') 75 | 76 | 77 | def edit_class(request): 78 | """ 79 | 编辑班级信息 80 | :param request: 81 | :return: 82 | """ 83 | # 如果是get请求,这里额外也需要查询下数据库,把原来的信息也展示出来 84 | if request.method == 'GET': 85 | # 获取客户端传过来的班级id 86 | nid = request.GET.get('nid') 87 | # 创建数据库连接 88 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 89 | # 执行游标 90 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 91 | # 执行sql语句 92 | cursor.execute('select id,title from class where id=%s', nid) 93 | # 获取查询到的所有数据 94 | result = cursor.fetchone() 95 | # print(result) 96 | # {'id': 1, 'title': '软件工程'} 97 | # 创建游标 98 | cursor.close() 99 | # 关闭连接 100 | conn.close() 101 | # 返回模板和数据 102 | return render(request, 'edit_class.html', {'result': result}) 103 | # post请求用来修改班级信息 104 | else: 105 | # nid = request.POST.get('nid') # 放到请求体 106 | nid = request.GET.get('nid') # 放到请求头 107 | title = request.POST.get('title') 108 | # 创建数据库连接 109 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 110 | # 创建游标 111 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 112 | # 执行sql语句 113 | cursor.execute('update class set title=%s where id = %s', [title, nid]) 114 | # 提交事务 115 | conn.commit() 116 | # 关闭游标 117 | cursor.close() 118 | # 关闭连接 119 | conn.close() 120 | return redirect('/user/class/') 121 | 122 | 123 | def del_class(request): 124 | # 获取客户端传过来的nid,我们要个根据nid来删除数据 125 | nid = request.GET.get('nid') 126 | # 创建连接对象 127 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 128 | # 创建游标 129 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 130 | # 执行sql语句 131 | cursor.execute('delete from class where id=%s', nid) 132 | # 提交事务 133 | conn.commit() 134 | # 关闭游标 135 | cursor.close() 136 | # 关闭连接 137 | conn.close() 138 | return redirect('/user/class/') 139 | 140 | 141 | def student(request): 142 | ''' 143 | 学生信息列表 144 | :param request:封装了请求相关的所有信息 145 | :return:返回模板和数据 146 | ''' 147 | # 创建连接对象 148 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 149 | # 创建游标 150 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 151 | # 查询学生信息列表 152 | cursor.execute( 153 | 'select student.id,student.name,class_id,class.title from student left join class on student.class_id=class.id') 154 | # 获取查询到的所有数据 155 | student_list = cursor.fetchall() 156 | paginator = Paginator(student_list, 1) 157 | current_page = request.GET.get('page') 158 | try: 159 | posts = paginator.page(current_page) 160 | except PageNotAnInteger as e: 161 | posts = paginator.page(1) 162 | except EmptyPage as e: 163 | posts = paginator.page(1) 164 | # 查询班级信息 165 | cursor.execute('select id,title from class') 166 | # 获取查询到的所有班级列表 167 | class_list = cursor.fetchall() 168 | # 关闭游标 169 | cursor.close() 170 | # 关闭连接 171 | conn.close() 172 | # 返回模板和数据 173 | return render(request, 'student.html', {'student_list': student_list, 'class_list': class_list, 'posts': posts}) 174 | 175 | 176 | def add_student(request): 177 | """ 178 | 添加学生信息 179 | :param request: 180 | :return: 181 | """ 182 | # 如果是get请求 183 | if request.method == 'GET': 184 | # 创建连接对象 185 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 186 | # 创建游标 187 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 188 | # 执行查询的sql语句 189 | cursor.execute("select id,title from class") 190 | # 获取查询到的所有数据 191 | classe_list = cursor.fetchall() 192 | # 关闭游标 193 | cursor.close() 194 | # 关闭连接 195 | conn.close() 196 | # 返回模板和数据 197 | return render(request, 'add_student.html', {'class_list': classe_list}) 198 | # 如果是post请求 199 | else: 200 | # 获取学生的名字 201 | name = request.POST.get('name') 202 | # 获取学生的班级id 203 | class_id = request.POST.get('class_id') 204 | # 创建连接 205 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 206 | # 创建游标 207 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 208 | # 将学生的名字和班级的id信息放到sql中 209 | cursor.execute("insert into student(name,class_id) values (%s,%s)", [name, class_id, ]) 210 | # 执行事务 211 | conn.commit() 212 | # 关闭游标 213 | cursor.close() 214 | # 关闭连接 215 | conn.close() 216 | # 返回模板 217 | return redirect('/user/student/') 218 | 219 | 220 | def edit_student(request): 221 | """ 222 | 编辑学生信息 223 | :param request: 224 | :return: 225 | """ 226 | # get请求时 227 | if request.method == 'GET': 228 | # 获取传过来的学生id 229 | nid = request.GET.get('nid') 230 | # 创建连接对象 231 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 232 | # 创建游标 233 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 234 | # 执行查询班级信息的sql 235 | cursor.execute("select id,title from class") 236 | # 获取所有班级信息 237 | class_list = cursor.fetchall() 238 | # 执行查询当前学生编号、名字和班级id的sql 239 | cursor.execute("select id,name,class_id from student where id=%s", nid) 240 | # 获取查询到的数据。因为数据只有一条,所以这里使用fetchone()就可以了 241 | current_student_info = cursor.fetchone() 242 | # 关闭游标 243 | cursor.close() 244 | # 关闭连接 245 | conn.close() 246 | # 返回模板和数据 247 | return render(request, 'edit_student.html', 248 | {'class_list': class_list, 'current_student_info': current_student_info}) 249 | # post请求时 250 | else: 251 | # 从url中获取学生的id 252 | nid = request.GET.get('nid') 253 | # 从请求体(form表单)中获取当前学生的姓名 254 | name = request.POST.get('name') 255 | # 从请求体中获取当前学生的班级id 256 | class_id = request.POST.get('class_id') 257 | # 创建练级 258 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 259 | # 创建游标 260 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 261 | # 执行sql语句 262 | cursor.execute("update student set name=%s,class_id=%s where id = %s", [name, class_id, nid]) 263 | # 提交事务 264 | conn.commit() 265 | # 关闭游标 266 | cursor.close() 267 | # 关闭连接 268 | conn.close() 269 | # 重定向到学生信息页面 270 | return redirect('/user/student/') 271 | 272 | 273 | def del_student(request): 274 | """ 275 | 删除学生信息 276 | :param request: 277 | :return: 278 | """ 279 | # 获取学生编号 280 | nid = request.GET.get('nid') 281 | # 创建连接 282 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 283 | # 创建游标 284 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 285 | # 执行sql 286 | cursor.execute('delete from student where id=%s', nid) 287 | # 提交事务 288 | conn.commit() 289 | # 关闭游标 290 | cursor.close() 291 | # 关闭连接 292 | conn.close() 293 | # 返回模板 294 | return redirect('/user/student/') 295 | 296 | 297 | def add_class_modal(request): 298 | """ 299 | 模态对话框的方式添加班级信息 300 | :param request: 301 | :return: 302 | """ 303 | # 从前台ajax提交的json字符串中{'title': $('#title').val()}获取班级名称 304 | title = request.POST.get('title') 305 | # 输入的班级名称的长度需要大于0 306 | # print(title) 307 | if len(title) > 0: 308 | # 创建连接 309 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 310 | # 创建游标 311 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 312 | # 执行sql 313 | cursor.execute('insert into class (title) values (%s)', title) 314 | # 提交事务 315 | conn.commit() 316 | # 关闭游标 317 | cursor.close() 318 | # 关闭连接 319 | conn.close() 320 | # 向前台返回ok 321 | return HttpResponse('ok') 322 | else: 323 | # 如果提交过来的班级名称长度是小于0的,向前台返回不能为空,给前台提示信息 324 | return HttpResponse('班级不能为空!') 325 | 326 | 327 | def edit_class_modal(request): 328 | ''' 329 | 模态对话框编辑班级信息 330 | ''' 331 | # 获取班级编号 332 | class_id = request.GET.get('class_id') 333 | # 获取班级名称 334 | class_title = request.GET.get('class_title') 335 | # 获取的名称长度要大于0 336 | if len(class_title) > 0: 337 | # 创建连接 338 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 339 | # 创建游标 340 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 341 | # 执行sql 342 | cursor.execute('update class set title=%s where id = %s', [class_title, class_id]) 343 | # 提交事务 344 | conn.commit() 345 | # 关闭游标 346 | cursor.close() 347 | # 关闭连接 348 | conn.close() 349 | # 向前台返回的data,前台通过这里来判断编辑是否完成 350 | return HttpResponse('ok') 351 | else: 352 | # 返回错误提示信息 353 | return HttpResponse('班级不能为空!') 354 | 355 | 356 | def del_class_modal(request): 357 | """ 358 | 模态对话框删除班级信息 359 | :param request: 360 | :return: 361 | """ 362 | # 获取班级编号,需要通过编号删除班级信息 363 | class_id = request.GET.get('class_id') 364 | print(class_id) 365 | # 创建连接 366 | conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') 367 | # 创建游标 368 | cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 369 | # 将班级id传到sql豫剧中并执行sql 370 | cursor.execute('delete from class where id=%s', class_id) 371 | # 提交事务 372 | conn.commit() 373 | # 关闭游标 374 | cursor.close() 375 | # 关闭连接 376 | conn.close() 377 | # 返回操作成功的标识 378 | return HttpResponse('ok') 379 | 380 | 381 | def add_student_modal(request): 382 | """ 383 | 模态对话框的方式添加班级信息 384 | :param request: 385 | :return: 386 | """ 387 | ret = {'status': True, 'msg': None} 388 | try: 389 | name = request.POST.get('name') 390 | class_id = request.POST.get('class_id') 391 | if len(name) <= 0 or len(class_id) <= 0: 392 | ret['status'] = False 393 | ret['msg'] = '学生姓名或班级不能为空' 394 | return HttpResponse(json.dumps(ret)) 395 | sqlhelper.modify(sql='insert into student(name,class_id) values(%s,%s)', args=[name, class_id]) 396 | except Exception as e: 397 | ret['status'] = False 398 | ret['msg'] = str(e) 399 | return HttpResponse(json.dumps(ret)) 400 | 401 | 402 | def edit_student_modal(request): 403 | """ 404 | 模态框编辑学生信息 405 | :param request: 406 | :return: 407 | """ 408 | ret = {'status': True, 'msg': None} 409 | try: 410 | student_id = request.POST.get('student_id') 411 | class_id = request.POST.get('class_id_edit') 412 | student_name = request.POST.get('student_name') 413 | sqlhelper.modify('update student set name=%s,class_id=%s where id=%s', 414 | [student_name, class_id, student_id]) 415 | except Exception as e: 416 | ret['status'] = False 417 | ret['msg'] = str(e) 418 | return HttpResponse(json.dumps(ret)) 419 | 420 | 421 | def del_student_modal(request): 422 | """ 423 | 模态框删除学生信息 424 | :param request: 425 | :return: 426 | """ 427 | ret = {'status': True, 'msg': None} 428 | try: 429 | student_id = request.GET.get('student_id') 430 | sqlhelper.modify('delete from student where id=%s', [student_id, ]) 431 | except Exception as e: 432 | ret['status'] = False 433 | ret['msg'] = str(e) 434 | return HttpResponse(json.dumps(ret)) 435 | 436 | 437 | def add_teacher(request): 438 | """ 439 | 添加教师 440 | :param request: 441 | :return: 442 | """ 443 | if request.method == 'GET': 444 | class_list = sqlhelper.get_list('select id,title from class', []) 445 | return render(request, 'add_teacher.html', {'class_list': class_list}) 446 | else: 447 | name = request.POST.get('name') 448 | obj = sqlhelper.SqlHelper() 449 | teacher_id = obj.create('insert into teacher(name) values (%s)', [name, ]) 450 | class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10'] 451 | # 多次连接,多次提交 452 | """ 453 | for class_id in class_ids: 454 | sqlhelper.modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', [teacher_id, class_id]) 455 | """ 456 | # 一次连接,多次提交 457 | """ 458 | for class_id in class_ids: 459 | obj.modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', [teacher_id, class_id]) 460 | obj.close() 461 | """ 462 | # 一次连接,一次提交 463 | data_list = [] # [(9, '8'), (9, '9'), (9, '10')] 464 | for class_id in class_ids: 465 | data_list.append((teacher_id, class_id)) 466 | obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', data_list) 467 | obj.close() 468 | return redirect('/user/teacher/') 469 | 470 | 471 | def teacher(request): 472 | """ 473 | 查询教师和任课班级信息 474 | :param request: 475 | :return: 476 | """ 477 | obj = sqlhelper.SqlHelper() 478 | teacher_list = obj.get_list( 479 | 'select teacher.id as tid,teacher.name,class.title from teacher left join teacher2class on teacher.id = teacher2class.teacher_id left join class on teacher2class.class_id = class.id ;', 480 | []) 481 | """ 482 | print(teacher_list) 483 | [ 484 | {'tid': 1, 'name': '李娇', 'title': '网络工程'}, 485 | {'tid': 1, 'name': '李娇', 'title': '计算机科学与技术'}, 486 | {'tid': 1, 'name': '李娇', 'title': '软件技术'}, 487 | {'tid': 1, 'name': '李娇', 'title': '软件工程'}, 488 | {'tid': 2, 'name': '李晓', 'title': '网络工程'}, 489 | {'tid': 2, 'name': '李晓', 'title': '软件工程'} 490 | ] 491 | """ 492 | 493 | result = {} 494 | for row in teacher_list: 495 | tid = row['tid'] 496 | if tid in result: 497 | result[tid]['titles'].append(row['title']) 498 | else: 499 | result[tid] = {'tid': row['tid'], 'name': row['name'], 'titles': [row['title'], ]} 500 | """ 501 | print(ret) 502 | { 503 | 1: {'tid': 1, 'name': '李娇', 'titles': ['网络工程', '计算机科学与技术', '软件技术', '软件工程']}, 504 | 2: {'tid': 2, 'name': '李晓', 'titles': ['网络工程', '软件工程']} 505 | } 506 | """ 507 | return render(request, 'teacher.html', {'teacher_list': result.values(), }) 508 | 509 | 510 | def edit_teacher(request): 511 | if request.method == 'GET': 512 | nid = request.GET.get('nid') 513 | obj = sqlhelper.SqlHelper() 514 | # 当前教师的信息 515 | teacher_info = obj.get_one('select id,name from teacher where id = %s', [nid, ]) 516 | # 当前教师的任教班级的id信息 517 | class_id_list = obj.get_list('select class_id from teacher2class where teacher_id=%s', [nid, ]) 518 | # 所有的班级信息 519 | class_list = obj.get_list('select id,title from class', []) 520 | """ 521 | print(teacher_list) # {'id': 2, 'name': '李晓'} 522 | print(class_list) # [{'id': 1, 'title': '软件工程'}, {'id': 8, 'title': '软件技术'}, {'id': 9, 'title': '计算机科学与技术'}, {'id': 10, 'title': '网络工程'}] 523 | print(class_id_list) # [{'class_id': 1}, {'class_id': 10}] 524 | """ 525 | obj.close() 526 | temp = [] 527 | for item in class_id_list: 528 | temp.append(item['class_id']) 529 | """ 530 | print(temp) # [1, 10] 531 | """ 532 | return render(request, 'edit_teacher.html', 533 | {'class_list': class_list, 'teacher_info': teacher_info, 'class_id_list': temp}) 534 | else: 535 | # 获取post请求的url上的参数 536 | nid = request.GET.get('nid') 537 | print(nid) 538 | name = request.POST.get('name') 539 | class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10'] 540 | obj = sqlhelper.SqlHelper() 541 | obj.modify('update teacher set name = %s where id = %s', [name, nid]) 542 | obj.modify('delete from teacher2class where teacher_id = %s', [nid]) 543 | data_list = [] # [('1', '1'), ('1', '8'), ('1', '9'), ('1', '10')] 544 | """ 545 | for class_id in class_ids: 546 | temp = (nid, class_id,) 547 | data_list.append(temp) 548 | """ 549 | # 使用lambda表达式 550 | func = lambda nid, class_id: data_list.append((nid, class_id)) 551 | for class_id in class_ids: 552 | func(nid, class_id) 553 | obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', data_list) 554 | return redirect('/user/teacher/') 555 | 556 | 557 | def add_teacher_modal(request): 558 | """ 559 | AJAX的方式添加教师信息 560 | :param request: 561 | :return: 562 | """ 563 | if request.method == 'GET': 564 | obj = sqlhelper.SqlHelper() 565 | class_list = obj.get_list('select id,title from class', []) 566 | import time 567 | # 这里是用来模拟用户网站压力比较大的情况下 568 | time.sleep(0.2) 569 | obj.close() 570 | return HttpResponse(json.dumps(class_list)) 571 | if request.method == 'POST': 572 | ret = {'status': True, 'msg': None} 573 | # 一般ajax请求要加上try 574 | try: 575 | name = request.POST.get('name') 576 | class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10'] 577 | # print(name,class_ids) #奈何 ['9', '10'] 578 | obj = sqlhelper.SqlHelper() 579 | teacher_id = obj.create('insert into teacher(name) values (%s) ', [name, ]) 580 | data_list = [] 581 | func = lambda item: data_list.append((teacher_id, item)) 582 | for item in class_ids: 583 | func(item) 584 | # print(data_list) # [(8, '8'), (8, '10')] 585 | obj.multiple_modify('insert teacher2class(teacher_id,class_id) values(%s,%s)', data_list) 586 | obj.close() 587 | except Exception as e: 588 | ret['status'] = False 589 | ret['msg'] = '处理失败!' 590 | return HttpResponse(json.dumps(ret)) 591 | 592 | 593 | def del_teacher_modal(request): 594 | """ 595 | AJAX的方式删除教师信息 596 | :param request: 597 | :return: 598 | """ 599 | if request.method == 'GET': 600 | ret = {'status': True, 'msg': None} 601 | try: 602 | obj = sqlhelper.SqlHelper() 603 | tid = request.GET.get('teacher_id') 604 | obj.modify('delete from teacher where id =%s', [tid]) 605 | obj.modify('delete from teacher2class where teacher_id = %s', [tid]) 606 | obj.close() 607 | except Exception as e: 608 | ret['status'] = False 609 | ret['msg'] = "删除失败!" 610 | return HttpResponse(json.dumps(ret)) 611 | -------------------------------------------------------------------------------- /static/js/jquery-3.5.1.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0