This commit is contained in:
awin-x 2024-07-11 15:46:31 +08:00
commit 8c26dcb169
33 changed files with 1025 additions and 0 deletions

BIN
db.sqlite3 Normal file

Binary file not shown.

1
exam/__init__.py Normal file
View File

@ -0,0 +1 @@
default_app_config = 'exam.apps.ExamConfig'

8
exam/admin.py Normal file
View File

@ -0,0 +1,8 @@
from django.contrib import admin
# Register your models here.
from .models import Question, Choice, CyberUser
admin.site.register(Question)
admin.site.register(Choice)
admin.site.register(CyberUser)

6
exam/apps.py Normal file
View File

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

129
exam/form.py Normal file
View File

@ -0,0 +1,129 @@
from django.forms import Form, fields
from django.core.exceptions import ValidationError
class RegisterForm(Form):
username = fields.CharField(
required=True,
min_length=2,
max_length=20,
error_messages={
'required': '用户名不可以为空!',
'min_length': '用户名应大于2位',
'max_length': '用户名应小于20位',
},
)
nickname = fields.CharField(
required=True,
min_length=2,
max_length=20,
error_messages={
'required': '昵称不可以为空!',
'min_length': '昵称应大于2位',
'max_length': '昵称应小于20位',
},
)
password1 = fields.CharField(
required=True,
min_length=6,
max_length=20,
error_messages={
'required': '密码不可以位空!',
'min_length': '密码应大于6位',
'max_length': '密码应小于20位',
},
)
password2 = fields.CharField(
required=True,
error_messages={
'required': '请再次输入密码!',
},
)
email = fields.EmailField(
required=True,
error_messages={
'required': '请随便填个邮箱吧...',
},
)
def clean_password2(self):
if not self.errors.get("password1"):
if self.cleaned_data["password2"] != self.cleaned_data["password1"]:
raise ValidationError("您输入的密码不一致,请重新输入!")
return self.cleaned_data
class LoginForm(Form):
username = fields.CharField(
required=True,
error_messages={
'required': '请输入用户名',
},
)
password = fields.CharField(
required=True,
error_messages={
'required': '请输入密码',
},
)
class CreateForm(Form):
text = fields.CharField(
required=True,
max_length=300,
error_messages={
'required': '请输入题目',
'max_length': '不得超过300字'
}
)
image = fields.ImageField(required=False)
a = fields.CharField(
required=True,
max_length=300,
error_messages={
'required': '请输入选项',
'max_length': '不得超过300字'
}
)
b = fields.CharField(
required=True,
max_length=300,
error_messages={
'required': '请输入选项',
'max_length': '不得超过300字'
}
)
c = fields.CharField(
required=True,
max_length=300,
error_messages={
'required': '请输入选项',
'max_length': '不得超过300字'
}
)
d = fields.CharField(
required=True,
max_length=300,
error_messages={
'required': '请输入选项',
'max_length': '不得超过300字'
}
)
answer = fields.ChoiceField(choices=(('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')))
class AnswerForm(Form):
questionID = fields.UUIDField()
answer = fields.ChoiceField(choices=(('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')))

View File

@ -0,0 +1,70 @@
# Generated by Django 5.0.7 on 2024-07-11 05:50
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='Question',
fields=[
('uid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
('question_text', models.CharField(max_length=300, unique=True, verbose_name='题目文本')),
('pub_date', models.DateTimeField(auto_now=True, verbose_name='发布日期')),
('image', models.ImageField(blank=True, null=True, upload_to='images/question_images/', verbose_name='图片')),
('choice_a', models.CharField(max_length=300)),
('choice_b', models.CharField(max_length=300)),
('choice_c', models.CharField(max_length=300)),
('choice_d', models.CharField(max_length=300)),
('answer', models.CharField(choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')], max_length=10)),
],
options={
'verbose_name': '问题',
'verbose_name_plural': '问题',
},
),
migrations.CreateModel(
name='CyberUser',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('uid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('username', models.CharField(max_length=15, unique=True, verbose_name='用户名')),
('nickname', models.CharField(blank=True, max_length=13, null=True, verbose_name='昵称')),
('email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='邮箱')),
('picture', models.ImageField(blank=True, null=True, upload_to='images/avatars', verbose_name='用户头像')),
('date_joined', models.DateTimeField(auto_now_add=True)),
('score', models.IntegerField(default=0)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'verbose_name': '用户',
'verbose_name_plural': '用户',
},
),
migrations.CreateModel(
name='Choice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice', models.CharField(choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')], max_length=10)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)),
('question', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='exam.question')),
],
),
]

View File

81
exam/models.py Normal file
View File

@ -0,0 +1,81 @@
import uuid
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractUser
from django.contrib.auth import get_user_model
# Create your models here.
class Question(models.Model):
uid = models.UUIDField(primary_key=True, default=uuid.uuid4, unique=True)
question_text = models.CharField(max_length=300, unique=True, verbose_name='题目文本')
pub_date = models.DateTimeField(auto_now=True, verbose_name='发布日期')
image = models.ImageField(upload_to='images/question_images/', verbose_name='图片', blank=True, null=True)
choice_a = models.CharField(max_length=300)
choice_b = models.CharField(max_length=300)
choice_c = models.CharField(max_length=300)
choice_d = models.CharField(max_length=300)
answer = models.CharField(choices=(('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')), max_length=10)
class Meta:
verbose_name = '问题'
verbose_name_plural = verbose_name
class UserManager(BaseUserManager): # 自定义Manager管理器
def _create_user(self, username, password, email, **kwargs):
if not username:
raise ValueError("请传入用户名!")
if not password:
raise ValueError("请传入密码!")
if not email:
raise ValueError("请传入邮箱地址!")
user = self.model(username=username, email=email, **kwargs)
user.set_password(password)
user.save()
return user
def create_user(self, username, password, email, **kwargs): # 创建普通用户
kwargs['is_superuser'] = False
return self._create_user(username, password, email, **kwargs)
def create_superuser(self, username, password, email, **kwargs): # 创建超级用户
kwargs['is_superuser'] = True
kwargs['is_staff'] = True
return self._create_user(username, password, email, **kwargs)
class CyberUser(AbstractUser): # 自定义User
uid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=15, verbose_name="用户名", unique=True)
nickname = models.CharField(max_length=13, verbose_name="昵称", null=True, blank=True)
email = models.EmailField(verbose_name="邮箱", null=True, blank=True)
picture = models.ImageField(upload_to="images/avatars", verbose_name="用户头像", null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
score = models.IntegerField(default=0)
USERNAME_FIELD = 'username' # 使用authenticate验证时使用的验证字段可以换成其他字段但验证字段必须是唯一的即设置了unique=True
REQUIRED_FIELDS = ['email'] # 创建用户时必须填写的字段除了该列表里的字段还包括password字段以及USERNAME_FIELD中的字段
EMAIL_FIELD = 'email' # 发送邮件时使用的字段
objects = UserManager()
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
class Meta:
verbose_name = "用户"
verbose_name_plural = verbose_name
class Choice(models.Model):
choice = models.CharField(choices=(('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')), max_length=10)
question = models.ForeignKey(Question, on_delete=models.DO_NOTHING)
user = models.ForeignKey(get_user_model(), on_delete=models.DO_NOTHING)

3
exam/tests.py Normal file
View File

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

12
exam/urls.py Normal file
View File

@ -0,0 +1,12 @@
from django.urls import path
from . import views
urlpatterns = (
path("", views.home, name="index"),
path("register/", views.register, name="register"),
path("login/", views.login_view, name="login"),
path("logout/", views.logout_view, name="logout"),
path("create/", views.create_question, name="create"),
path("question/", views.get_question, name="get_question"),
path("answer/", views.answer, name="answer")
)

201
exam/views.py Normal file
View File

@ -0,0 +1,201 @@
import uuid
from django.core.files import File
from django.http import JsonResponse, Http404
from django.shortcuts import render, redirect
from .form import RegisterForm, LoginForm, CreateForm, AnswerForm
from .models import CyberUser, Question, Choice
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
# Create your views here.
def home(request):
content = {'user': request.user}
return render(request, 'home.html', content)
def register(request):
if request.method == 'GET':
return render(request, 'register.html', {'form': RegisterForm()})
elif request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
nickname = form.cleaned_data['nickname']
password = form.cleaned_data['password1']
email = form.cleaned_data['email']
username_exist = CyberUser.objects.filter(username=username).exists()
if username_exist:
return JsonResponse({"code": 400,
"message": "验证失败",
"data": {"username": "",
"password1": "",
"password2": "",
"email": "",
},
})
CyberUser.objects.create_user(
username=username,
nickname=nickname,
password=password,
email=email,
)
return JsonResponse({"code": 200,
"message": "验证通过,已注册",
"data": {"username": "",
"password1": "",
"password2": "",
"email": "",
},
})
else:
return JsonResponse({"code": 400, "message": "验证失败", "data": {"username": form.errors.get("username"),
"password1": form.errors.get("password1"),
"password2": form.errors.get("password2"),
"email": form.errors.get("email")}})
else:
raise Http404
def login_view(request):
if request.method == 'GET':
return render(request, 'login.html', {'form': LoginForm()})
elif request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user and user.is_active:
login(request, user)
request.session['username'] = username
request.session.set_expiry(1800)
return JsonResponse(
{
"code": 200,
"message": '登陆成功',
"data": username,
}
)
elif user and user.is_active:
return JsonResponse(
{
"code": 400,
"message": "用户状态错误,请联系管理员修正",
"data": "user is not active",
}
)
else:
return JsonResponse(
{
"code": 400,
"message": "用户名或密码错误",
"data": None,
}
)
else:
return JsonResponse(
{
"code": 400,
"message": "验证失败,用户名或密码格式错误",
"data": form.errors.get(),
}
)
else:
raise Http404
def logout_view(request):
logout(request)
return redirect('/exam/login')
@login_required
def create_question(request):
if request.method == 'GET':
return render(request, 'create.html', {'form': CreateForm})
elif request.method == 'POST':
form = CreateForm(request.POST, request.FILES)
if form.is_valid():
text = form.cleaned_data['text']
image = form.cleaned_data['image']
a = form.cleaned_data['a']
b = form.cleaned_data['b']
c = form.cleaned_data['c']
d = form.cleaned_data['d']
answer = form.cleaned_data['answer']
new_question = Question(
question_text=text,
choice_a=a,
choice_b=b,
choice_c=c,
choice_d=d,
answer=answer,
)
if image:
new_question.image = File(image, name=f'{str(uuid.uuid4())}.jpg')
new_question.save()
return JsonResponse(
{
'code': 200,
'message': 'success',
'data': '',
}
)
else:
return JsonResponse(
{
'code': 400,
'message': '参数不正确',
'data': form.errors
}
)
@login_required
def get_question(request):
user = request.user
question = Question.objects.exclude(choice__user=user).order_by('?').first()
return render(request, "question.html", {'question': question, 'form': AnswerForm, 'user': request.user})
@login_required
def answer(request):
if request.method == 'POST':
form = AnswerForm(request.POST)
if form.is_valid():
user = request.user
user_ans = form.cleaned_data['answer']
questionID = form.cleaned_data['questionID']
question = Question.objects.get(uid=questionID)
if Choice.objects.filter(user=user, question=question).exists():
return JsonResponse(
{
'code': 200,
'message': '该问题已经回答过了',
'data': '',
}
)
choice = Choice(user=user, question=question, choice=user_ans)
choice.save()
if user_ans == question.answer:
user.score = user.score + 1
user.save()
return JsonResponse(
{
'code': 200,
'message': 'success',
'data': {'correction': user_ans == question.answer},
}
)
else:
return JsonResponse(
{
'code': 400,
'message': '参数错误',
'data': '表单不可用',
}
)
else:
return Http404

22
manage.py Normal file
View File

@ -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', '不夜城考试.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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

2
static/js/jquery-3.6.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

17
templates/base.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
{% load static %}
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
{% block script %}{% endblock script %}
</head>
<body>
{% block body %}{% endblock body %}
</body>
<script src={% static 'js/jquery-3.6.0.min.js' %}></script>
</html>

80
templates/create.html Normal file
View File

@ -0,0 +1,80 @@
{% extends 'base.html' %}
{% block tittle %}登陆{% endblock tittle %}
{% block body %}
<h1>创建题目</h1>
<form id="loginForm" onsubmit="event.preventDefault(); submitForm();" enctype="multipart/form-data">
{% csrf_token %}
<label for="text">题目文本:</label>
<input type="text" id="text" name="text" required><br>
<input type="file" name="image" id="image" accept="image/jpg" onchange="imgChange(this);"> <!--文件上传选择按钮-->
<img id="image-preview" width="50%" src=""/><br>
<label for="A">A选项:</label>
<input type="text" id="A" name="a" required><br>
<label for="B">B选项:</label>
<input type="text" id="B" name="b" required><br>
<label for="C">C选项:</label>
<input type="text" id="C" name="c" required><br>
<label for="D">D选项:</label>
<input type="text" id="D" name="d" required><br>
<label>答案:</label><br>
<input type="radio" id="A" name="answer" value="A" checked>
<label for="A">A</label><br>
<input type="radio" id="B" name="answer" value="B">
<label for="B">B</label><br>
<input type="radio" id="C" name="answer" value="C">
<label for="C">C</label><br>
<input type="radio" id="D" name="answer" value="D">
<label for="D">D</label><br>
<button type="submit">提交题目</button>
</form>
<!-- 错误信息显示区域 -->
<div id="errorMessage" style="display: none;"></div>
{% endblock body %}
{% block script %}
<script>
function imgChange(obj) {
var file = document.getElementById("image");
var imgUrl = window.URL.createObjectURL(file.files[0]);
var img = document.getElementById('image-preview');
img.setAttribute('src', imgUrl); // 修改img标签src属性值
};
function submitForm() {
var formData = new FormData($('#loginForm')[0]);
$.ajax({
url: "{% url 'exam:create' %}", // Django模板标签用于生成URL
type: "POST",
data: formData,
contentType: false, // 告诉jQuery不要设置Content-Type请求头
processData: false, // 告诉jQuery不要处理发送的数据
success: function(response) {
if (response.code === 200) {
alert(response.message); // 成功时的消息框
} else {
alert(response.message); // 显示错误信息
displayErrors(response.data);
}
},
error: function() {
alert("An error occurred while processing your request.");
}
});
}
function displayErrors(errors) {
$('#errorMessage').html('');
for (let key in errors) {
if (errors.hasOwnProperty(key)) {
let message = errors[key];
$('#errorMessage').append('<p>' + message + '</p>');
}
}
$('#errorMessage').show();
}
</script>
{% endblock script %}

14
templates/home.html Normal file
View File

@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% block tittle %}不夜城考试中心{% endblock tittle %}
{% block body %}
<h1>不夜城考试中心</h1>
{% if user.is_active %}
<p>欢迎,{{ user.username }}</p>
<a href="/exam/logout">退出</a>
<a href="/exam/question">开始答题</a>
{% else %}
<a href="/exam/login">登陆</a>
<a href="/exam/register">注册</a>
{% endif %}
{% endblock body %}

51
templates/login.html Normal file
View File

@ -0,0 +1,51 @@
{% extends 'base.html' %}
{% block tittle %}登陆{% endblock tittle %}
{% block body %}
<h1>登陆</h1>
<form id="loginForm" onsubmit="event.preventDefault(); submitForm();">
{% csrf_token %}
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required><br>
<button type="submit">登陆</button>
<a href="/exam/register">注册</a>
</form>
<!-- 错误信息显示区域 -->
<div id="errorMessage" style="display: none;"></div>
{% endblock body %}
{% block script %}
<script>
function submitForm() {
$.ajax({
url: "{% url 'exam:login' %}", // Django模板标签用于生成URL
type: "POST",
data: $('#loginForm').serialize(),
success: function(response) {
if (response.code === 200) {
alert(response.message); // 成功时的消息框
window.location.href = "/exam";
} else {
alert(response.message); // 显示错误信息
}
},
error: function() {
alert("An error occurred while processing your request.");
}
});
}
function displayErrors(errors) {
$('#errorMessage').html('');
for (let key in errors) {
if (errors.hasOwnProperty(key)) {
let message = errors[key];
$('#errorMessage').append('<p>' + message + '</p>');
}
}
$('#errorMessage').show();
}
</script>
{% endblock script %}

78
templates/question.html Normal file
View File

@ -0,0 +1,78 @@
{% extends 'base.html' %}
{% block tittle %}随机题目{% endblock tittle %}
{% block body %}
<h1>题目</h1>
{% if question %}
<form id="loginForm" onsubmit="event.preventDefault(); submitForm();" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="questionID" value="{{ question.uid }}">
<h2>题目文本:</h2>
<p>{{ question.question_text }}</p><br>
{% if question.image %}
<img id="image-preview" width="50%" src="{{ question.image.url }}"/><br>
{% endif %}
<label>选择:</label><br>
<input type="radio" id="A" name="answer" value="A" checked>
<label for="A">A</label><br>
<input type="radio" id="B" name="answer" value="B">
<label for="B">B</label><br>
<input type="radio" id="C" name="answer" value="C">
<label for="C">C</label><br>
<input type="radio" id="D" name="answer" value="D">
<label for="D">D</label><br>
<button type="submit">提交题目</button>
</form>
{% else %}
<p>没有提穆啦</p>
<h3>你的分数是:{{ user.score }}</h3>
{% endif %}
<!-- 错误信息显示区域 -->
<div id="errorMessage" style="display: none;"></div>
{% endblock body %}
{% block script %}
<script>
function imgChange(obj) {
var file = document.getElementById("image");
var imgUrl = window.URL.createObjectURL(file.files[0]);
var img = document.getElementById('image-preview');
img.setAttribute('src', imgUrl); // 修改img标签src属性值
};
function submitForm() {
var formData = new FormData($('#loginForm')[0]);
$.ajax({
url: "{% url 'exam:answer' %}", // Django模板标签用于生成URL
type: "POST",
data: formData,
contentType: false, // 告诉jQuery不要设置Content-Type请求头
processData: false, // 告诉jQuery不要处理发送的数据
success: function(response) {
if (response.code === 200) {
alert(response.message); // 成功时的消息框
} else {
alert(response.message); // 显示错误信息
displayErrors(response.data);
}
},
error: function() {
alert("An error occurred while processing your request.");
}
});
}
function displayErrors(errors) {
$('#errorMessage').html('');
for (let key in errors) {
if (errors.hasOwnProperty(key)) {
let message = errors[key];
$('#errorMessage').append('<p>' + message + '</p>');
}
}
$('#errorMessage').show();
}
</script>
{% endblock script %}

56
templates/register.html Normal file
View File

@ -0,0 +1,56 @@
{% extends 'base.html' %}
{% block tittle %}注册页面{% endblock tittle %}
{% block body %}
<h1>注册</h1>
<form id="registerForm" onsubmit="event.preventDefault(); submitForm();">
{% csrf_token %}
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required><br>
<label for="nickname">昵称:</label>
<input type="text" id="nickname" name="nickname" required><br>
<label for="password1">密码:</label>
<input type="password" id="password1" name="password1" required><br>
<label for="password2">确认密码:</label>
<input type="password" id="password2" name="password2" required><br>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required><br>
<button type="submit">Register</button>
</form>
<!-- 错误信息显示区域 -->
<div id="errorMessage" style="display: none;"></div>
{% endblock body %}
{% block script %}
<script>
function submitForm() {
$.ajax({
url: "{% url 'exam:register' %}", // Django模板标签用于生成URL
type: "POST",
data: $('#registerForm').serialize(),
success: function(response) {
if (response.code === 200) {
alert(response.message); // 成功时的消息框
} else {
displayErrors(response.data); // 显示错误信息
alert(response.message);
}
},
error: function() {
alert("An error occurred while processing your request.");
}
});
}
function displayErrors(errors) {
$('#errorMessage').html('');
for (let key in errors) {
if (errors.hasOwnProperty(key)) {
let message = errors[key];
$('#errorMessage').append('<p>' + message + '</p>');
}
}
$('#errorMessage').show();
}
</script>
{% endblock script %}

View File

16
不夜城考试/asgi.py Normal file
View File

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

137
不夜城考试/settings.py Normal file
View File

@ -0,0 +1,137 @@
"""
Django settings for 不夜城考试 project.
Generated by 'django-admin startproject' using Django 5.0.7.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-!78yd6se#zw2x9##j$x@$j9+q)cf!7%pham38azqz+p3j)chwe'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'exam',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = '不夜城考试.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media',
],
},
},
]
WSGI_APPLICATION = '不夜城考试.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static/'),
os.path.join(BASE_DIR, 'media/'),
]
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
AUTH_USER_MODEL = 'exam.CyberUser'

25
不夜城考试/urls.py Normal file
View File

@ -0,0 +1,25 @@
"""
URL configuration for 不夜城考试 project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the "include()" function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from . import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('exam/', include(('exam.urls', 'exam'), namespace='exam')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

16
不夜城考试/wsgi.py Normal file
View File

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