@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/../../../../../../:\djangoProject\djangoProject\djangoProject\the_online_test_system\.idea/dataSources/
|
||||
/dataSources.local.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8" project-jdk-type="Python SDK" />
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/the_online_test_system.iml" filepath="$PROJECT_DIR$/.idea/the_online_test_system.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="django" name="Django">
|
||||
<configuration>
|
||||
<option name="rootFolder" value="$MODULE_DIR$" />
|
||||
<option name="settingsModule" value="the_online_test_system/settings.py" />
|
||||
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
|
||||
<option name="environment" value="<map/>" />
|
||||
<option name="doNotUseTestRunner" value="false" />
|
||||
<option name="trackFilePattern" value="migrations" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||
<option name="TEMPLATE_FOLDERS">
|
||||
<list>
|
||||
<option value="$MODULE_DIR$/../the_online_test_system\templates" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LoginConfig(AppConfig):
|
||||
name = 'login'
|
@ -0,0 +1,59 @@
|
||||
import os
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
def random_str(length=4):
|
||||
""" 随机字符串 默认长度 4
|
||||
|
||||
:param length: 默认长度 4
|
||||
:return:
|
||||
"""
|
||||
return ''.join(random.sample(string.ascii_letters, length))
|
||||
|
||||
|
||||
def random_color(s=1, e=255):
|
||||
""" 随机 RGB 颜色
|
||||
|
||||
:param s: 起始值, 0-255
|
||||
:param e: 结束时, 0-255
|
||||
:return: (r, g, b)
|
||||
"""
|
||||
return random.randint(s, e), random.randint(s, e), random.randint(s, e)
|
||||
|
||||
|
||||
def veri_code(length=4, width=160, height=40, size=28):
|
||||
""" 生成验证码图片
|
||||
|
||||
:param length: 验证码字符串长度
|
||||
:param width: 图片宽度
|
||||
:param height: 图片高度
|
||||
:param size: 字体大小
|
||||
:return: (验证码图片, 验证码字符串)
|
||||
"""
|
||||
# 创建Image对象
|
||||
image = Image.new('RGB', (width, height), (255, 255, 255))
|
||||
# 创建Font对象
|
||||
file = os.path.dirname(os.path.abspath(__file__))
|
||||
font = ImageFont.truetype(f'{file}/FZSTK.ttf', size)
|
||||
# 创建Draw对象
|
||||
draw = ImageDraw.Draw(image)
|
||||
# 随机颜色填充每个像素
|
||||
for x in range(0, width, 2):
|
||||
for y in range(height):
|
||||
draw.point((x, y), fill=random_color(64, 255))
|
||||
# 验证码
|
||||
code = random_str(length)
|
||||
# 随机颜色验证码写到图片上
|
||||
for t in range(length):
|
||||
draw.text((40 * t + 5, 5), code[t], font=font, fill=random_color(32, 127))
|
||||
# 模糊滤镜
|
||||
# image = image.filter(ImageFilter.BLUR)
|
||||
return image, code
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
img, code = veri_code()
|
||||
with open('test.png', 'wb') as f:
|
||||
img.save(f)
|
@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-08 08:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserInfo',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('identity', models.CharField(max_length=4, verbose_name='身份')),
|
||||
('name', models.CharField(max_length=32, verbose_name='姓名')),
|
||||
('id_number', models.CharField(max_length=32, verbose_name='学号/教师编号')),
|
||||
('phone', models.CharField(max_length=32, unique=True, verbose_name='手机')),
|
||||
('username', models.CharField(max_length=32, unique=True, verbose_name='账号')),
|
||||
('password', models.CharField(max_length=32, verbose_name='密码')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class UserInfo(models.Model):
|
||||
"""
|
||||
用户列表
|
||||
用于记录用户基本信息
|
||||
"""
|
||||
identity = models.CharField(max_length=4, verbose_name="身份", blank=False, null=False)
|
||||
name = models.CharField(max_length=32, verbose_name="姓名", blank=False, null=False)
|
||||
id_number = models.CharField(max_length=32, verbose_name="学号/教师编号", blank=False, null=False)
|
||||
phone = models.CharField(max_length=32, verbose_name="手机", unique=True, blank=False, null=False)
|
||||
username = models.CharField(max_length=32, verbose_name="账号", unique=True, blank=False, null=False)
|
||||
password = models.CharField(max_length=32, verbose_name="密码", blank=False, null=False)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,252 @@
|
||||
body .bgimg img{
|
||||
position:absolute;
|
||||
width: auto;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
top: 5px;
|
||||
height: 100%;
|
||||
left:0%;
|
||||
top: 0%;
|
||||
padding: 0;
|
||||
margin:0;
|
||||
z-index: 0;
|
||||
}
|
||||
body {
|
||||
font-family: PingFang SC,HarmonyOS_Regular,Helvetica Neue,Microsoft YaHei,sans-serif!important;
|
||||
font-weight: 400;
|
||||
overflow-x: auto;
|
||||
background-color: var(--graph_bg_regular);
|
||||
}
|
||||
|
||||
body {
|
||||
/* font-size: 14px; */
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
/* -webkit-text-size-adjust: 100%; */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
color: #18191c;
|
||||
background-color: #f6f7f8;
|
||||
/* min-width: 1100px; */
|
||||
}
|
||||
|
||||
.header-bgimg {
|
||||
position: absolute;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left:0;
|
||||
z-index: 100;
|
||||
/* width: 1519.2px; */
|
||||
width: 1535px;
|
||||
/* height: 155px; */
|
||||
height: 120px;
|
||||
}
|
||||
header .header_bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0px;
|
||||
z-index: 1002;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* padding: 0 24px; */
|
||||
max-width: 2560px;
|
||||
/* width: 100%; */
|
||||
width: 1535px;
|
||||
height: 64px;
|
||||
}
|
||||
body ul {
|
||||
/* 取消小原点 */
|
||||
list-style-type: none;
|
||||
}
|
||||
body ul li {
|
||||
margin: 15px;
|
||||
}
|
||||
header .header_bar .left_entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
body a {
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
header span {
|
||||
color: white;
|
||||
/* font:14px "PingFang SC",HarmonyOs_re */
|
||||
}
|
||||
|
||||
.header_center {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
background-color: #fff;
|
||||
width: 400px;
|
||||
height: 32px;
|
||||
border-radius: 13px;
|
||||
}
|
||||
.header_bar .header_center .reseach {
|
||||
position: relative;
|
||||
/* display: inline; */
|
||||
top: -7px;
|
||||
/* left: 2px; */
|
||||
|
||||
width: 360px;
|
||||
height: 25px;
|
||||
line-height: 30px;
|
||||
border-radius: 13px;
|
||||
border-width: 0px;
|
||||
outline:none;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* header .header_bar .right_entry {
|
||||
position: relative;
|
||||
left: 100px;
|
||||
} */
|
||||
header right_last {
|
||||
position:absolute;
|
||||
}
|
||||
|
||||
header .header_bar .right_entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.right_last button {
|
||||
/* box-shadow: 5px 5px rgb(109, 247, 71); */
|
||||
/* blur:5px; */
|
||||
background:transparent;/*按钮背景透明 */
|
||||
/* background-color: pink; */
|
||||
border-radius: 14px;
|
||||
border-color: greenyellow;
|
||||
border: width 1px; /*边框透明*/
|
||||
outline:none; /*点击后没边框*/
|
||||
font-size: 24px;
|
||||
border-radius: 22px;
|
||||
}
|
||||
.mybody {
|
||||
position: relative;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
left: -8px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
top: 60px;
|
||||
/* background: #000; */
|
||||
|
||||
}
|
||||
.body_left{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
.body_center {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -220px;
|
||||
/* left: 900px; */
|
||||
width: 200px;
|
||||
/* height: 600px; */
|
||||
/* background-color: pink; */
|
||||
}
|
||||
|
||||
.body_center ul {
|
||||
/* position: absolute; */
|
||||
/* top: -200px;
|
||||
left: 50px; */
|
||||
position: relative;
|
||||
left: 20px;
|
||||
display:inline-block;
|
||||
|
||||
}
|
||||
.body_center ul li{
|
||||
margin: 10px;
|
||||
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
|
||||
font-weight: 700;
|
||||
/* font-style: italic; */
|
||||
font-size: 50px;
|
||||
position: center;
|
||||
}
|
||||
|
||||
|
||||
.body_right {
|
||||
position: absolute;
|
||||
display: block;
|
||||
/* width: 100px;
|
||||
height: 100px; */
|
||||
top: 70px;
|
||||
right: 0;
|
||||
/* background-color: #fff; */
|
||||
/* background: rgba(249, 246, 246, 0.3); */
|
||||
font-size: 20px;
|
||||
/* margin: 20px */
|
||||
}
|
||||
|
||||
.body_right table tr{
|
||||
margin: 20px;
|
||||
}
|
||||
.body_right input {
|
||||
width: 250px;
|
||||
height: 23px;
|
||||
border-color: aqua;
|
||||
border-radius: 18px;
|
||||
margin: 20px;
|
||||
}
|
||||
.body_right table .sign_ {
|
||||
position:relative;
|
||||
width: 220px;
|
||||
height: 40px;
|
||||
left: 50px;
|
||||
/*color: white;*/
|
||||
/*background:rgba(0,0,0, 0.3);*/
|
||||
font-size: 24px;
|
||||
}
|
||||
.body_right table span {
|
||||
/* border: red; */
|
||||
position: relative;
|
||||
/*background-color:aqua;*/
|
||||
/*left: 150px;*/
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 18px;
|
||||
margin: 30px;
|
||||
}
|
||||
/*.body_right table {*/
|
||||
/* margin: 0px;*/
|
||||
/* width: 50px;*/
|
||||
/*}*/
|
||||
.body_right table .add input{
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
width: 15px;
|
||||
top: 4px;
|
||||
/*left: 20px;*/
|
||||
font-size: 16px;
|
||||
/*color: aliceblue;*/
|
||||
}
|
||||
.body_right table .add span {
|
||||
border-radius: 16px;
|
||||
border: 4px;
|
||||
border-color: aqua;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color:#aedab5;
|
||||
}
|
||||
|
||||
.body_right table .add a {
|
||||
width: 110px;
|
||||
border-radius: 16px;
|
||||
|
||||
background-color:#aedab5;
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,102 @@
|
||||
|
||||
.mybody{padding: 0;margin: 0;}
|
||||
|
||||
.body_left{
|
||||
position: relative;
|
||||
/* top: 40px; */
|
||||
/* width: 100vw;
|
||||
height: 100vh; */
|
||||
width: 750px;
|
||||
height: 600px;
|
||||
/* background: #82ccdd; */
|
||||
display:inline-block;
|
||||
/* justify-content: center;
|
||||
align-items: center; */
|
||||
}
|
||||
/* 显示框 */
|
||||
div.scroll-photo{
|
||||
position: absolute;
|
||||
/* width: 400px;
|
||||
height: 300px; */
|
||||
/* width: 800px; */
|
||||
width: 765px;
|
||||
height: 450px;
|
||||
left: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* 内置图片的排列总宽度 */
|
||||
div.photos{
|
||||
position: absolute;
|
||||
/* width: 1200px;
|
||||
height: 300px; */
|
||||
width: 22500px;
|
||||
height: 450px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
div.photos img{
|
||||
position: relative;
|
||||
/* width: 400px;
|
||||
height: 300px; */
|
||||
width: 800px;
|
||||
height: 450px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.index ul{
|
||||
position: absolute;
|
||||
display: grid;
|
||||
bottom: -10px;
|
||||
left: 40%;
|
||||
transform: translateX(-50%);
|
||||
list-style: none;
|
||||
width: 150px;
|
||||
grid-template: 1fr/repeat(3,1fr);
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
div.index ul::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 55px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
z-index: -1;
|
||||
/* background: #d63031; */
|
||||
background: rgb(0, 255, 255);
|
||||
}
|
||||
|
||||
div.index ul li{
|
||||
position: relative;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
color: #FFF;
|
||||
background: rgba(0,0,0,.5);
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
div.photos{
|
||||
animation:scroll 12s steps(3,end);
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
div.index ul::after{
|
||||
animation:index-scroll 12s steps(3,end);
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
/* 图片移动像素 */
|
||||
@keyframes scroll{
|
||||
to{
|
||||
transform: translateX(-2400px);
|
||||
}
|
||||
}
|
||||
/*下标移动像素 */
|
||||
@keyframes index-scroll{
|
||||
to{
|
||||
transform: translateX(165px);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
body {
|
||||
background-image: url(img/zc3.png);
|
||||
/* background-repeat: repeat-x; */
|
||||
position:relative;
|
||||
background-position-y: -100px;
|
||||
/* background-position-x: 50px; */
|
||||
/* top: -200px; */
|
||||
}
|
||||
div {
|
||||
position:relative;
|
||||
top: 80px;
|
||||
left: 35%;
|
||||
width: 500px;
|
||||
border: 0ch;
|
||||
border: 4px solid aqua;
|
||||
background-color: rgba(255,255,255,0.6);
|
||||
}
|
||||
div h4 {
|
||||
text-align: center;
|
||||
font-size: 36px;
|
||||
font-style: inherit;
|
||||
font-family:Georgia, 'Times New Roman', Times, serif
|
||||
}
|
||||
td {
|
||||
position:relative;
|
||||
left: 15%;
|
||||
}
|
||||
input {
|
||||
width: 300px;
|
||||
height: 30px;
|
||||
border-radius: 18px;
|
||||
border-color: aqua;
|
||||
position: relative;
|
||||
/* left: 25%; */
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.tk input{
|
||||
position:relative;
|
||||
width: 15px;
|
||||
vertical-align: middle;
|
||||
/* height: 100%; */
|
||||
/* margin:0px; */
|
||||
/* line-height: 72px; */
|
||||
/* right: 50%; */
|
||||
}
|
||||
select {
|
||||
width: 300px;
|
||||
height: 30px;
|
||||
border-radius: 18px;
|
||||
border-color: aqua;
|
||||
position: relative;
|
||||
/* left: 25%; */
|
||||
margin: 20px;
|
||||
}
|
||||
a {
|
||||
position: relative;
|
||||
left: 20%;
|
||||
text-decoration: none;
|
||||
}
|
After Width: | Height: | Size: 783 KiB |
After Width: | Height: | Size: 373 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 588 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 645 KiB |
After Width: | Height: | Size: 708 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 7.0 MiB |
After Width: | Height: | Size: 2.7 MiB |
After Width: | Height: | Size: 3.3 MiB |
After Width: | Height: | Size: 6.5 MiB |
After Width: | Height: | Size: 3.3 MiB |
After Width: | Height: | Size: 724 B |
After Width: | Height: | Size: 388 KiB |
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
{% load static %}
|
||||
<head>
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>注册页面</title>
|
||||
<link rel="stylesheet" href="{% static 'css/zhuce.css' %}">
|
||||
</head>
|
||||
<body>
|
||||
<form method="post">
|
||||
{%csrf_token%}
|
||||
<div>
|
||||
<h4>启航题库</h4>
|
||||
<table width="500">
|
||||
<!-- 第一行 -->
|
||||
<!-- <tr>
|
||||
<td>
|
||||
我是:
|
||||
</td>
|
||||
<td>
|
||||
<label><input type="radio" name="id"><img src="../images/men.jpg" width="25">老师</label>
|
||||
<label><input type="radio" name="id"> <img src="../images/women.jpg" width="25" >学生</label>
|
||||
</td>
|
||||
</tr> -->
|
||||
<!-- 第二行 -->
|
||||
<tr>
|
||||
<td>
|
||||
<select name="identity" required="required">
|
||||
<option>我的身份</option>
|
||||
<option name=identity" value="老师">老师</option>
|
||||
<option name="identity" value="学生">学生</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 第三行 -->
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" name="name" required="required" placeholder="我的姓名">
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 第四行 -->
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" name="id_number" required="required" placeholder="学号or工号">
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 第六行 -->
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" name="phone" required="required" placeholder="手机号码">
|
||||
|
||||
</td>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" name="username" required="required" placeholder="用户名">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="password" name="password" required="required" placeholder="密码">
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
<!-- 第八行 -->
|
||||
<br>
|
||||
{% if error_msg %}<p><strong>{{ error_msg }}</strong></p>{% endif %}
|
||||
<br>
|
||||
<tr>
|
||||
<td class>
|
||||
<input type="submit" value="注册">
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 第九行 -->
|
||||
<tr>
|
||||
<td class="tk">
|
||||
<input type="radio"> 我同意注册条款和会员加入标准
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 第十行 -->
|
||||
<tr>
|
||||
<td >
|
||||
<a href="#"> 我是会员,立即登录</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,21 @@
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'login'
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
|
||||
path('register/', views.register),
|
||||
|
||||
path('login/', views.login, name='login'),
|
||||
|
||||
path('dologin/', views.dologin, name='dologin'),
|
||||
|
||||
path('logout/', views.logout, name='logout'),
|
||||
|
||||
path('captcha_img/', views.captcha_img, name='captcha_img'),
|
||||
|
||||
]
|
||||
|
@ -0,0 +1,145 @@
|
||||
from django.shortcuts import render, HttpResponse, redirect
|
||||
from pymysql import IntegrityError
|
||||
from io import BytesIO
|
||||
from login.models import UserInfo
|
||||
from django.core.paginator import Paginator, Page
|
||||
from django.conf import settings
|
||||
from login.common import captcha
|
||||
|
||||
|
||||
def home(request):
|
||||
return render(request, 'home.html')
|
||||
|
||||
|
||||
def register(request):
|
||||
"""
|
||||
注册模块
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if request.method == 'GET':
|
||||
return render(request, 'zhuce.html')
|
||||
|
||||
# 获取用户提交的数据
|
||||
try:
|
||||
identity = request.POST.get("identity")
|
||||
name = request.POST.get("name")
|
||||
id_number = request.POST.get("id_number")
|
||||
phone = request.POST.get("phone")
|
||||
username = request.POST.get("username")
|
||||
password = request.POST.get("password")
|
||||
|
||||
# 添加到数据库
|
||||
UserInfo.objects.create(identity=identity, name=name, id_number=id_number, phone=phone, username=username, password=password)
|
||||
|
||||
# 一个跳转
|
||||
#
|
||||
#
|
||||
# 之后跳转至登录界面
|
||||
#
|
||||
return redirect('login:login')
|
||||
except IntegrityError:
|
||||
error_msg = '该手机号或用户名已被注册!'
|
||||
return render(request, 'zhuce.html', {'error_msg': error_msg} )
|
||||
|
||||
|
||||
def server_error(request):
|
||||
error_msg = '该手机号或用户名已被注册!'
|
||||
return HttpResponse("")
|
||||
|
||||
|
||||
# def login00(request):
|
||||
#
|
||||
# if request.method == 'GET':
|
||||
# return render(request, 'login.html')
|
||||
#
|
||||
# error_msg = ""
|
||||
# user = request.POST.get('email')
|
||||
# pwd = request.POST.get('password')
|
||||
#
|
||||
# temp_RawQuerySet = UserInfo.objects.raw('select * from app02_userfo')
|
||||
#
|
||||
# for temp in temp_RawQuerySet:
|
||||
# if temp.username == user and temp.password == pwd:
|
||||
# if temp.identity == '老师':
|
||||
# return redirect('http://www.baidu.com')
|
||||
# else:
|
||||
# return redirect('http://www.baidu.com')
|
||||
# else:
|
||||
# # 用户密码不匹配
|
||||
# error_msg = '用户名或密码错误'
|
||||
# return render(request, 'login.html', {'error_msg': error_msg})
|
||||
|
||||
|
||||
def login(request):
|
||||
# 从cookie中获取用户名和密码
|
||||
username = request.COOKIES.get('username')
|
||||
password = request.get_signed_cookie('pwd', None, salt='pwdsalt')
|
||||
if username and password:
|
||||
return render(request, 'login.html', {'username': username, 'pwd': password})
|
||||
else:
|
||||
return render(request, 'login.html')
|
||||
|
||||
|
||||
def dologin(request):
|
||||
|
||||
# 获取表单中提交的验证码
|
||||
check_code = request.POST.get('check_code')
|
||||
# 获取session会话中保存的code
|
||||
session_checkcode = request.session.get('check_code')
|
||||
if check_code and check_code.lower() == session_checkcode.lower():
|
||||
# 从登录表单中获取用户名和密码及是否勾选了记住密码
|
||||
username = request.POST.get('username')
|
||||
password = request.POST.get('password')
|
||||
rember = request.POST.get('rember')
|
||||
response = HttpResponse()
|
||||
|
||||
temp_RawQuerySet = UserInfo.objects.raw('select * from login_userinfo')
|
||||
|
||||
for temp in temp_RawQuerySet:
|
||||
if temp.username == username and temp.password == password:
|
||||
# ## 存入基本信息到session ## #
|
||||
request.session['username'] = username
|
||||
request.session['password'] = password
|
||||
request.session['id_number'] = temp.id_number
|
||||
request.session['name'] = temp.name
|
||||
if rember == 'rember':
|
||||
# 勾选了记住用户名和密码
|
||||
# 将用户名和密码保存到cookie中
|
||||
response.set_cookie('username', username, max_age=3 * 24 * 3600)
|
||||
response.set_signed_cookie('pwd', password, salt='pwdsalt', max_age=3 * 24 * 3600)
|
||||
else:
|
||||
# 删除cookie中的之前保存用户名和密码
|
||||
response.delete_cookie('username')
|
||||
response.delete_cookie('pwd')
|
||||
|
||||
if temp.identity == '老师':
|
||||
return redirect('teacher_client:teacher_client')
|
||||
# return render(request, 'teacher_client.html', {'username': temp.username})
|
||||
else:
|
||||
return redirect('student_client:student_client')
|
||||
|
||||
# 用户密码不匹配
|
||||
response.delete_cookie('username')
|
||||
response.delete_cookie('pwd')
|
||||
error_msg = '用户名或密码错误'
|
||||
return render(request, 'login.html', {'error_msg1': error_msg})
|
||||
else:
|
||||
error_msg = '验证码错误'
|
||||
return render(request, 'login.html', {'error_msg': error_msg})
|
||||
|
||||
|
||||
def logout(request):
|
||||
response = HttpResponse()
|
||||
response.delete_cookie('username')
|
||||
response.delete_cookie('pwd')
|
||||
request.session.flush()
|
||||
return response and redirect('login:login')
|
||||
|
||||
|
||||
def captcha_img(request):
|
||||
stream = BytesIO()
|
||||
img, code = captcha.veri_code()
|
||||
img.save(stream, 'PNG')
|
||||
request.session['check_code'] = code
|
||||
return HttpResponse(stream.getvalue())
|
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'the_online_test_system.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class StudentClientConfig(AppConfig):
|
||||
name = 'student_client'
|
@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,11 @@
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'student_client'
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
path("student_client/", views.student_client, name = "student_client")
|
||||
|
||||
]
|
@ -0,0 +1,7 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def student_client(request):
|
||||
"""学生端口"""
|
||||
if request.method == "GET":
|
||||
return render(request, "student_client.html")
|
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TeacherClientConfig(AppConfig):
|
||||
name = 'teacher_client'
|
@ -0,0 +1,14 @@
|
||||
import random
|
||||
|
||||
|
||||
def random_num():
|
||||
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
|
||||
'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r',
|
||||
's', 't', 'u', 'v', 'w', 'x',
|
||||
'y', 'z']
|
||||
temp = random.sample(L, 5)
|
||||
a, b, c, d, e = temp
|
||||
code = str(a)+str(b)+str(c)+str(d)+str(e)
|
||||
return code
|
@ -0,0 +1,17 @@
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from django.shortcuts import HttpResponse, redirect
|
||||
|
||||
|
||||
class AuthMiddleware(MiddlewareMixin):
|
||||
|
||||
def process_request(self, request):
|
||||
# 首先排除那些不需要登录的urls
|
||||
if request.path_info == '/' or request.path_info == '/register/' or request.path_info == '/dologin/':
|
||||
return None
|
||||
# 获取当前访问用户登录时存入的session信息
|
||||
username = request.session.get('username')
|
||||
password = request.session.get('password')
|
||||
# 若不为空,则已经登录
|
||||
if username and password:
|
||||
return None
|
||||
return HttpResponse('请登录')
|
@ -0,0 +1,20 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-09 08:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='questionBank',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,36 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-14 11:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='classTable',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=32, verbose_name='姓名')),
|
||||
('id_number', models.CharField(max_length=32, verbose_name='学号/教师编号')),
|
||||
('phone', models.CharField(max_length=32, unique=True, verbose_name='手机')),
|
||||
('classCode', models.CharField(default='', max_length=6, verbose_name='加课码')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='teacherClass',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=32, verbose_name='姓名')),
|
||||
('id_number', models.CharField(max_length=32, verbose_name='学号/教师编号')),
|
||||
('classCode', models.CharField(default='', max_length=20, verbose_name='加课码')),
|
||||
('classname', models.CharField(default='', max_length=20, verbose_name='课程名')),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='questionBank',
|
||||
),
|
||||
]
|
@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-15 09:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0002_auto_20220414_1945'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='questionBank',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('qus_imfomation', models.CharField(max_length=1000, verbose_name='题目信息')),
|
||||
('qus_A', models.CharField(max_length=1000, verbose_name='选项A')),
|
||||
('qus_B', models.CharField(max_length=1000, verbose_name='选项B')),
|
||||
('qus_C', models.CharField(max_length=1000, verbose_name='选项C')),
|
||||
('qus_D', models.CharField(max_length=1000, verbose_name='选项D')),
|
||||
('qus_ans', models.CharField(max_length=100, verbose_name='答案')),
|
||||
('que_classcode', models.CharField(max_length=10, verbose_name='所属班级')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-15 09:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0003_questionbank'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='questionbank',
|
||||
name='que_classcode',
|
||||
field=models.CharField(max_length=1000, verbose_name='所属班级'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='questionbank',
|
||||
name='qus_ans',
|
||||
field=models.CharField(max_length=1000, verbose_name='答案'),
|
||||
),
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-15 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0004_auto_20220415_1755'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='questionbank',
|
||||
name='que_time',
|
||||
field=models.CharField(default='', max_length=200, verbose_name='存入时间'),
|
||||
),
|
||||
]
|
@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-15 14:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0005_questionbank_que_time'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='testQuestionBank',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('qus_imfomation', models.CharField(max_length=1000, verbose_name='题目信息')),
|
||||
('qus_A', models.CharField(max_length=1000, verbose_name='选项A')),
|
||||
('qus_B', models.CharField(max_length=1000, verbose_name='选项B')),
|
||||
('qus_C', models.CharField(max_length=1000, verbose_name='选项C')),
|
||||
('qus_D', models.CharField(max_length=1000, verbose_name='选项D')),
|
||||
('qus_ans', models.CharField(max_length=1000, verbose_name='答案')),
|
||||
('test_code', models.CharField(max_length=1000, verbose_name='所属班级')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.4 on 2022-04-16 02:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teacher_client', '0006_testquestionbank'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='testquestionbank',
|
||||
name='test_time',
|
||||
field=models.CharField(default='', max_length=200, verbose_name='考试时间'),
|
||||
),
|
||||
]
|
@ -0,0 +1,45 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
# class questionBank(models.Model):
|
||||
# """用于存储题目数据"""
|
||||
|
||||
|
||||
class teacherClass(models.Model):
|
||||
"""记录班级加课码"""
|
||||
name = models.CharField(max_length=32, verbose_name="姓名", blank=False, null=False)
|
||||
id_number = models.CharField(max_length=32, verbose_name="学号/教师编号", blank=False, null=False)
|
||||
classCode = models.CharField(max_length=20, verbose_name="加课码", default='')
|
||||
classname = models.CharField(max_length=20, verbose_name="课程名", default='')
|
||||
|
||||
|
||||
class classTable(models.Model):
|
||||
"""班级表"""
|
||||
name = models.CharField(max_length=32, verbose_name="姓名", blank=False, null=False)
|
||||
id_number = models.CharField(max_length=32, verbose_name="学号/教师编号", blank=False, null=False)
|
||||
phone = models.CharField(max_length=32, verbose_name="手机", unique=True, blank=False, null=False)
|
||||
classCode = models.CharField(max_length=6, verbose_name="加课码", default='')
|
||||
|
||||
|
||||
class questionBank(models.Model):
|
||||
"""用于保存用户上传提交的题目"""
|
||||
qus_imfomation = models.CharField(max_length=1000, verbose_name="题目信息", blank=False, null=False)
|
||||
qus_A = models.CharField(max_length=1000, verbose_name="选项A", blank=False, null=False)
|
||||
qus_B = models.CharField(max_length=1000, verbose_name="选项B", blank=False, null=False)
|
||||
qus_C = models.CharField(max_length=1000, verbose_name="选项C", blank=False, null=False)
|
||||
qus_D = models.CharField(max_length=1000, verbose_name="选项D")
|
||||
qus_ans = models.CharField(max_length=1000, verbose_name="答案", blank=False, null=False)
|
||||
que_classcode = models.CharField(max_length=1000, verbose_name="所属班级", blank=False, null=False)
|
||||
que_time = models.CharField(max_length=200, verbose_name="存入时间", default="")
|
||||
|
||||
|
||||
class testQuestionBank(models.Model):
|
||||
"""考试信息表"""
|
||||
qus_imfomation = models.CharField(max_length=1000, verbose_name="题目信息", blank=False, null=False)
|
||||
qus_A = models.CharField(max_length=1000, verbose_name="选项A", blank=False, null=False)
|
||||
qus_B = models.CharField(max_length=1000, verbose_name="选项B", blank=False, null=False)
|
||||
qus_C = models.CharField(max_length=1000, verbose_name="选项C", blank=False, null=False)
|
||||
qus_D = models.CharField(max_length=1000, verbose_name="选项D")
|
||||
qus_ans = models.CharField(max_length=1000, verbose_name="答案")
|
||||
test_code = models.CharField(max_length=1000, verbose_name="所属班级", blank=False, null=False)
|
||||
test_time = models.CharField(max_length=200, verbose_name="考试时间", default='')
|
@ -0,0 +1,47 @@
|
||||
*{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
.page {
|
||||
display: block;
|
||||
position: relative;
|
||||
/* top: 400px; */
|
||||
left: 40px;
|
||||
}
|
||||
.all{
|
||||
width: 100%;
|
||||
/* width: 100px; */
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
/* left: 30px; */
|
||||
/* justify-content: center; */
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
/*偷懒才用的id*/
|
||||
#inputs input{
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
margin: 10px;
|
||||
}
|
||||
.info {
|
||||
position: relative;
|
||||
left: 100px;
|
||||
}
|
||||
#table{
|
||||
display: inline-block;
|
||||
width: 90%;
|
||||
}
|
||||
tr{
|
||||
width: 100%;
|
||||
margin: 10px;
|
||||
}
|
||||
td{
|
||||
text-align: center;
|
||||
/* width: 50%; */
|
||||
width: 200px;
|
||||
height: 10vh;
|
||||
border: 1px solid black;
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
table
|
||||
{
|
||||
border-collapse: collapse;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table td, table th
|
||||
{
|
||||
border: 1px solid #cad9ea;
|
||||
color: #666;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
table thead th
|
||||
{
|
||||
background-color: #CCE8EB;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
table tr:nth-child(odd)
|
||||
{
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
table tr:nth-child(even)
|
||||
{
|
||||
background: #F5FAFA;
|
||||
}
|
||||
|
||||
/*ul,li{ padding:0; margin:0;list-style:none}*/
|
||||
/*.nav{border:1px solid #000; width:510px; overflow:hidden}*/
|
||||
/*.nav li{ line-height:22px; float:left; padding:0 5px;}*/
|
||||
/*.nav li a:hover{ color:#F00}*/
|
||||
/*nav li{line-height:22px; float:left; padding:0 6px;}*/
|
||||
/*nav li a{ color:#009900}*/
|