/error_code_map/
/ec_user/*
/diagnose/*
/admin/*
This commit is contained in:
pzc-x99 2025-02-28 23:05:31 +08:00
commit f56b66d8f1
71 changed files with 4108 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/upload_file
/generate_paper
*.pyc

View File

8
authentication/admin.py Normal file
View File

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

6
authentication/apps.py Normal file
View File

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

View File

@ -0,0 +1,31 @@
from rest_framework.authentication import TokenAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import CustomToken
from datetime import timedelta
from django.utils import timezone
from functools import wraps
class CustomTokenAuthentication(TokenAuthentication):
def authenticate(self, request):
# 获取请求中的 token
token_key = request.headers.get('token')
if token_key:
# 移除前缀 (如果有 "Token " 前缀的话)
if token_key.startswith('Token '):
token_key = token_key[6:]
# print(token_key)
try:
# 获取自定义的 Token 对象
token = CustomToken.objects.get(key=token_key)
# 检查 token 是否过期
if token.expiration_date < timezone.now():
raise AuthenticationFailed('Token has expired.')
return (token.user, token) # 返回用户和 token
except CustomToken.DoesNotExist:
raise AuthenticationFailed('Invalid token.')
raise AuthenticationFailed('Authorization header missing or invalid.')

View File

@ -0,0 +1,32 @@
# Generated by Django 4.2.19 on 2025-02-26 08:21
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='CustomToken',
fields=[
('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('extra_info', models.CharField(blank=True, max_length=255, null=True)),
('last_used', models.DateTimeField(auto_now=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'Token',
'verbose_name_plural': 'Tokens',
'abstract': False,
},
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-26 08:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='customtoken',
name='expiration_date',
field=models.DateTimeField(blank=True, null=True),
),
]

View File

24
authentication/models.py Normal file
View File

@ -0,0 +1,24 @@
from django.db import models
# Create your models here.
from rest_framework.authtoken.models import Token
class CustomToken(Token):
# 在 Token 上添加更多字段(可以根据需求自定义)
extra_info = models.CharField(max_length=255, null=True, blank=True) # 示例附加信息字段
last_used = models.DateTimeField(auto_now=True) # 记录最后一次使用的时间
expiration_date = models.DateTimeField(null=True, blank=True) # 记录 Token 的过期时间
def __str__(self):
# 返回 Token 的字符串表示,包括用户名和 key
return f"Token for {self.user.username} - {self.key}"
def get_user_info(self):
# 可以提供一个方法来获取与 Token 关联的用户的更多信息
return {
"username": self.user.username,
"email": self.user.email,
"role": self.user.groups.first().name if self.user.groups.exists() else "No role"
}

3
authentication/tests.py Normal file
View File

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

6
authentication/urls.py Normal file
View File

@ -0,0 +1,6 @@
from django.urls import path
from .views import MyProtectedView
urlpatterns = [
path('', MyProtectedView.as_view(), name='protected-view'),
]

19
authentication/views.py Normal file
View File

@ -0,0 +1,19 @@
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from authentication.authentication import CustomTokenAuthentication
class MyProtectedView(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
# 只有认证通过的用户可以访问这个视图
print(request.user.id) # 访问当前用户
return Response({"message": "This is a protected view!"})

4
celerybeat-schedule.bak Normal file
View File

@ -0,0 +1,4 @@
'entries', (0, 6)
'__version__', (512, 15)
'tz', (1024, 23)
'utc_enabled', (1536, 4)

BIN
celerybeat-schedule.dat Normal file

Binary file not shown.

4
celerybeat-schedule.dir Normal file
View File

@ -0,0 +1,4 @@
'entries', (0, 6)
'__version__', (512, 15)
'tz', (1024, 23)
'utc_enabled', (1536, 4)

0
diagnose/__init__.py Normal file
View File

9
diagnose/admin.py Normal file
View File

@ -0,0 +1,9 @@
from django.contrib import admin
# Register your models here.
from . models import Papers
@admin.register(Papers)
class PaperAdmin(admin.ModelAdmin):
list_display = ('id', 'uuid', 'status', 'created_at', 'updated_at')

6
diagnose/apps.py Normal file
View File

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

BIN
diagnose/ch.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 KiB

253
diagnose/dp_views.py Normal file
View File

@ -0,0 +1,253 @@
# -*- coding: utf-8 -*-
import os
from openai import OpenAI
import markdown2
import pdfkit
from django.conf import settings
from django.http import JsonResponse, FileResponse
from celery import shared_task
import uuid
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from authentication.authentication import CustomTokenAuthentication
from django.core.exceptions import ObjectDoesNotExist
from .models import Papers
from ec_user.models import SchoolInfo
import json
# ============== PYdoc ===================
# from docx import Document
# import pypandoc
# pypandoc.download_pandoc()
# ================ weasyprint ===========
# 库用不了
# from weasyprint import HTML
# HTML(string=html).write_pdf("output.pdf")
class DpArguments():
subject = "数学"
textbook_version = "人教版"
start_grade = 8
start_semester = 1
start_chapter = 1
end_grade = 9
end_semester = 1
end_chapter = 1
student = {
"grade": 8,
"age": 10,
"school": "民族小学"
}
def __getstate__(self):
# 返回一个字典,包含所有需要序列化的属性
state = self.__dict__.copy()
# 如果你不想序列化某个属性,可以从字典中删除
# 例如: del state['student']
return state
def __setstate__(self, state):
# 用字典中的数据恢复对象状态
self.__dict__.update(state)
def generate_html_paper(md_result, file_path_name):
# 写到md中
md_file = open(f'{file_path_name}.md', 'w', encoding='utf-8')
md_file.write(md_result)
md_file.close()
# 从md中读出来再写到html中
md_read_file = open(f'{file_path_name}.md', 'r', encoding='utf-8')
md_text = md_read_file.read()
md_read_file.close()
html = markdown2.markdown(md_text)
html_write_file = open(f'{file_path_name}.html', 'w', encoding='utf-8')
html_write_file.write(
"""<head>
<meta charset="utf-8">
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
</head>"""+html)
html_write_file.close()
def convert_to_pdf(file_path_name):
# =============== pdfkit ================
# 从html中读出来再写到pdf中
f = open(f'{file_path_name}.html', 'r', encoding='utf-8')
content = f.read()
f.close()
config = pdfkit.configuration(wkhtmltopdf=settings.WKHTMLTOPDF_PATH)
pdfkit.from_string(content, f'{file_path_name}.pdf', configuration=config)
@shared_task
def async_wraper(file_path_name, uuid_str, subject, textbook_version, start_grade, \
start_semester, start_chapter, end_grade, end_semester, end_chapter, student):
# client = OpenAI(
# api_key = settings.OPAI_API_KEY,
# base_url = settings.OPAI_BASE_URL,
# )
# completion = client.chat.completions.create(
# model = "deepseek-r1-250120", # your model endpoint ID
# messages = [
# {"role": "system", "content": "你是教学助手"},
# # {"role": "user",
# # "content": f"请根据以下信息生成一份检测卷:学科为{subject},教材版本是{textbook_version},\
# # 检测范围从{start_grade}年级{start_semester}学期{start_chapter}章\
# # 到{end_grade}年级{end_semester}学期{end_chapter}章,学生年级为{student.get('grade')},\
# # 年龄为{student.get('age')},所在学校是{student.get('school')}。\
# # 根据答题所需时间一个半小时设置题量。题目有梯度。\
# # 试卷题目为{subject}{textbook_version}检测卷。只生成题目,不输出答案及说明等其他内容。"
# # },
# {"role": "user", "content": f"""请严格按照以下要求生成一份{subject}检测卷:
# 【试卷信息】
# 1. 标题:**{subject}{textbook_version}综合检测卷**
# 2. 检测范围:{start_grade}年级{start_semester}学期第{start_chapter}章 至
# {end_grade}年级{end_semester}学期第{end_chapter}章
# 3. 适用对象:{student.get('school')} {student.get('grade')}年级学生(年龄{student.get('age')}
# 【命题要求】
# 1. 题型结构:
# - 按难度梯度分为基础题60%、中档题30%、提高题10%
# - 根据学科特点设计合理的题型(如数学可设置选择题/填空题/计算题/应用题,语文可设置阅读理解/文言文/写作等)
# - 同一知识点不重复考查
# 2. 题量控制:
# - 总题数控制在18-22题以优秀学生完成时间约75分钟为标准
# - 选择题不超过5题填空题不超过6题
# - 需包含至少1道综合应用题理科或材料分析题文科
# 3. 内容要求:
# - 严格按照指定章节范围命题
# - 题目表述清晰无歧义,数字单位标注完整
# - 禁止出现需图片辅助的题目
# - 数学类题目需给出必要公式位置(如"提示可用公式____"
# 【输出格式】
# 仅输出以下内容:
# 1. 试卷标题(加粗居中)
# 2. 考试说明含总分值100分、考试时长、姓名班级填写处
# 3. 分模块的题目内容(标注题型、分值和题号)
# 4. "——以下为题目区域——" 分隔线
# 禁止包含:
# - 答案及解析
# - 评分标准
# - 额外说明文字
# - markdown格式及特殊符号"""}
# ],
# )
# generate_html_paper(completion.choices[0].message.content, file_path_name)
import time
time.sleep(30)
generate_html_paper(""" # Test md""", file_path_name)
try:
obj = Papers.objects.get(uuid=uuid_str) # 只获取一个对象
obj.status = 'D'
obj.updated_at = timezone.now()
obj.save()
except ObjectDoesNotExist:
print("warning: record not found")
class MyProtectedGeneratePaper(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def post(self, request):
user = request.user
uuid_str = str(uuid.uuid4())
radom_path = user.username +'_'+ uuid_str
file_path_name = os.path.join(settings.BASE_DIR, 'generate_paper', radom_path)
# 处理 POST 请求,更新用户的联系信息
try:
data = json.loads(request.body)
subject = data.get("subject")
textbook_version = data.get("textbook_version")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# auth_subjects = user.subjects.all()
if not user.subjects.filter(name=subject).exists():
print("subject", subject)
return JsonResponse({"error_code": "2001"}, status=403)
if user.subject_usage_count <= 0:
return JsonResponse({"error_code": "2002"}, status=403)
dp_args = DpArguments()
dp_args.subject = subject
dp_args.textbook_version = textbook_version
school_obj = SchoolInfo.objects.filter(user=user).first()
if school_obj is None:
return JsonResponse({"error_code": "2003"}, status=403)
dp_args.student['age'] = user.age
dp_args.student['school'] = school_obj.school_name
dp_args.student['grade'] = school_obj.grade
print(dp_args.student, dp_args.subject, dp_args.textbook_version, dp_args.start_grade, dp_args.start_semester,\
dp_args.start_chapter, dp_args.end_grade, dp_args.end_semester, dp_args.end_chapter)
# 调用异步任务
obj = Papers.objects.create(uuid=uuid_str, user=user, status='P')
obj.save()
user.subject_usage_count = user.subject_usage_count - 1
user.save()
async_wraper.delay(file_path_name, uuid_str, \
dp_args.subject, dp_args.textbook_version, dp_args.start_grade, dp_args.start_semester, dp_args.start_chapter, \
dp_args.end_grade, dp_args.end_semester, dp_args.end_chapter, dp_args.student)
return JsonResponse({"status": "success", "uuid": uuid_str})
class MyProtectedGenerateCheck(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户的联系信息
try:
data = json.loads(request.body)
uuid_str = data.get("uuid")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
try:
# print(uuid_str)
obj = Papers.objects.get(uuid=uuid_str, user=user) # 只获取一个对象
if obj.status == 'D':
return JsonResponse({"status": "done", "download_url": f'/diagnose/download/?uuid_str={uuid_str}'})
else:
return JsonResponse({"status": "processing", "download_url": None})
except ObjectDoesNotExist:
return JsonResponse({"error_code": "2004"}, status=404)
class MyProtectedDownloadPaper(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
uuid_str = request.query_params.get('uuid_str', None)
if not uuid_str:
return JsonResponse({"error": "Missing uuid_str in query parameters"}, status=400)
user = request.user
username = user.username
file_path_name = os.path.join(settings.BASE_DIR, 'generate_paper', f'{username}_{uuid_str}')
# 检查文件是否存在
print(file_path_name)
if not os.path.exists(file_path_name + ".html"):
return JsonResponse({"error_code": "2005"}, status=403)
convert_to_pdf(file_path_name)
try:
# 直接将文件路径传递给 FileResponse
response = FileResponse(open(file_path_name+".pdf", 'rb'), as_attachment=True)
response['Content-Disposition'] = f'attachment; filename="{username}_{uuid_str}.pdf"'
return response
except Exception as e:
return JsonResponse({"error": f"Failed to open file: {str(e)}"}, status=500)

View File

@ -0,0 +1,26 @@
# Generated by Django 4.2.19 on 2025-02-27 06:23
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Papers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(max_length=100)),
('status', models.CharField(choices=[('C', '任务创建'), ('P', '生成中'), ('D', '已完成')], default='C', max_length=1)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.19 on 2025-02-27 06:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('diagnose', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='papers',
name='created_at',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.AddField(
model_name='papers',
name='updated_at',
field=models.DateTimeField(auto_now=True, null=True),
),
]

View File

19
diagnose/models.py Normal file
View File

@ -0,0 +1,19 @@
from django.db import models
from ec_user.models import EcUser
# Create your models here.
class Papers(models.Model):
STATUS_CHOICES = (
('C', '任务创建'),
('P', '生成中'),
('D', '已完成')
)
uuid = models.CharField(max_length=100) # 试卷的唯一标识符
# 定义一个与EcUser一对多关联的外键
user = models.ForeignKey(EcUser, on_delete=models.CASCADE) # 当EcUser被删除时关联的Papers也会被删除
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default='C') # 默认值设置为'C'
created_at = models.DateTimeField(auto_now_add=True,null=True, blank=True) # 创建时间
updated_at = models.DateTimeField(auto_now=True,null=True, blank=True) # 更新时间
def __str__(self):
return self.user.username + '的试卷'

43
diagnose/openaitest.py Normal file
View File

@ -0,0 +1,43 @@
import os
from openai import OpenAI
import base64
client = OpenAI(
api_key = 'd04d386a-7c67-4927-8251-171a236583a6',
base_url = "https://ark.cn-beijing.volces.com/api/v3",
)
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
# 将图片转为Base64编码
# 需要传给大模型的图片
image_path = "ch.jpg"
base64_image = encode_image(image_path)
# Image input:
response = client.chat.completions.create(
model="doubao-1-5-vision-pro-32k-250115",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "图中是几个语文题目,帮我分析一下,我是否做对了",
},
{
"type": "image_url",
"image_url": {
# 需要注意传入Base64编码前需要增加前缀 data:image/{图片格式};base64,{Base64编码}
# PNG图片"url": f"data:image/png;base64,{base64_image}"
# JEPG图片"url": f"data:image/jpeg;base64,{base64_image}"
# WEBP图片"url": f"data:image/webp;base64,{base64_image}"
"url": f"data:image/jpg;base64,{base64_image}"
},
},
],
}
],
)
print(response.choices[0].message.content)

138
diagnose/te.py Normal file
View File

@ -0,0 +1,138 @@
import _thread as thread
import base64
import datetime
import hashlib
import hmac
import json
from urllib.parse import urlparse
import ssl
from datetime import datetime
from time import mktime
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time
# websocket-client
import websocket
class Ws_Param(object):
# 初始化
def __init__(self, APPID, APIKey, APISecret, gpt_url):
self.APPID = APPID
self.APIKey = APIKey
self.APISecret = APISecret
self.host = urlparse(gpt_url).netloc
self.path = urlparse(gpt_url).path
self.gpt_url = gpt_url
# 生成url
def create_url(self):
# 生成RFC1123格式的时间戳
now = datetime.now()
date = format_date_time(mktime(now.timetuple()))
# 拼接字符串
signature_origin = "host: " + self.host + "\n"
signature_origin += "date: " + date + "\n"
signature_origin += "GET " + self.path + " HTTP/1.1"
# 进行hmac-sha256进行加密
signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),
digestmod=hashlib.sha256).digest()
signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8')
authorization_origin = f'api_key="{self.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
# 将请求的鉴权参数组合为字典
v = {
"authorization": authorization,
"date": date,
"host": self.host
}
# 拼接鉴权参数生成url
url = self.gpt_url + '?' + urlencode(v)
# 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释比对相同参数时生成的url与自己代码生成的url是否一致
return url
# 收到websocket错误的处理
def on_error(ws, error):
print("### error:", error)
# 收到websocket关闭的处理
def on_close(ws, status_code, reason):
print("")
# 收到websocket连接建立的处理
def on_open(ws):
thread.start_new_thread(run, (ws,))
def run(ws, *args):
data = json.dumps(gen_params(appid=ws.appid, question=ws.question))
ws.send(data)
# 收到websocket消息的处理
def on_message(ws, message):
# print(message)
data = json.loads(message)
code = data['header']['code']
if code != 0:
print(f'请求错误: {code}, {data}')
ws.close()
else:
choices = data["payload"]["choices"]
status = choices["status"]
content = choices["text"][0]["content"]
print(content, end='')
if status == 2:
ws.close()
def gen_params(appid, question):
"""
通过appid和用户的提问来生成请参数
"""
data = {
"header": {
"app_id": appid,
"uid": "1234"
},
"parameter": {
"chat": {
"domain": "general",
"random_threshold": 0.5,
"max_tokens": 4096,
"auditing": "default"
}
},
"payload": {
"message": {
"text": [
{"role": "user", "content": question}
]
}
}
}
return data
def main(appid, api_key, api_secret, gpt_url, question):
wsParam = Ws_Param(appid, api_key, api_secret, gpt_url)
websocket.enableTrace(False)
wsUrl = wsParam.create_url()
ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close, on_open=on_open)
ws.appid = appid
ws.question = question
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
print("end")
if __name__ == "__main__":
# 测试时候在此处正确填写相关信息即可运行
main(appid = "0c0a6c2f",
api_secret = "Y2UwZjhiYTRhNDM1NjkwNzg3NmEzMTA3",
api_key = "42e836c7c40e1ff9dacac9de6b689bb1",
gpt_url = "ws://spark-api.xf-yun.com/v3.5/chat",
question = '帮我生成一份高三年级英语期中考试试卷,要求包括选择题、填空题、完形填空题、阅读理解题和写作题,每道题都有答案和解析。请直接输出试卷内容,不要输出其他信息。'
)

36
diagnose/upload_views.py Normal file
View File

@ -0,0 +1,36 @@
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from authentication.authentication import CustomTokenAuthentication
import uuid
import os
from django.conf import settings
from django.http import JsonResponse
from rest_framework import status
class MyProtectedUploadfile(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def post(self, request):
user = request.user
uuid_str = str(uuid.uuid4())
save_file_path = os.path.join(settings.BASE_DIR, 'upload_file', user.username, uuid_str)
os.makedirs(os.path.dirname(save_file_path), exist_ok=True)
# 获取上传的文件
uploaded_file = request.FILES.get('file')
if not uploaded_file:
return JsonResponse({"error": "No file uploaded."}, status=status.HTTP_400_BAD_REQUEST)
# 保存文件
try:
with open(save_file_path, 'wb+') as destination:
for chunk in uploaded_file.chunks():
destination.write(chunk)
except:
return JsonResponse({"error": "Error saving file."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return JsonResponse({"message": "File uploaded successfully."}, status=status.HTTP_200_OK)

11
diagnose/urls.py Normal file
View File

@ -0,0 +1,11 @@
from django.urls import path
from .dp_views import MyProtectedGeneratePaper, MyProtectedGenerateCheck, MyProtectedDownloadPaper
from .upload_views import MyProtectedUploadfile
urlpatterns = [
path('', MyProtectedGeneratePaper.as_view(), name='api_generate_paper'),
path('check/', MyProtectedGenerateCheck.as_view(), name='api_generate_check'),
path('download/', MyProtectedDownloadPaper.as_view(), name='api_download_paper'),
path('upload/', MyProtectedUploadfile.as_view(), name='api_upload_file')
]

0
ec_user/__init__.py Normal file
View File

66
ec_user/admin.py Normal file
View File

@ -0,0 +1,66 @@
from django.contrib import admin
"""
设置后台管理的全局参数
"""
admin.site.site_header = '诊断应用后台'
admin.site.site_title = '诊断服务端'
admin.site.index_title = '诊断服务端'
"""
设置后台管理的全局参数
结束
"""
from django.urls import reverse
from django.utils.html import format_html
# Register your models here.
from . models import EcUser, Subject, SchoolInfo
from django import forms
class UcUserInfoForm(forms.ModelForm):
class Meta:
model = EcUser
fields = '__all__'
widgets = {
'subjects': forms.CheckboxSelectMultiple, # 使用复选框小部件
}
@admin.register(EcUser)
class UcUserInfo(admin.ModelAdmin):
# 在列表视图中显示哪些字段
list_display = ('username','id', 'gender', 'dob', 'political_status', 'custom_link')
# 通过 fieldsets 分组字段并定义显示顺序
fieldsets = (
(None, {
'fields': ('username', 'password') # 先显示用户名和密码
}),
('Personal Information', {
'fields': ('name', 'gender', 'age', 'ethnicity', 'dob', 'id_card_number', 'political_status', 'subjects', 'subject_usage_count')
}),
)
# 还可以通过 'search_fields' 添加搜索功能
search_fields = ('name', 'id_card_number')
# 可以设置过滤选项,方便后台管理
list_filter = ('gender', 'political_status')
# 可选:设置只读字段
# readonly_fields = ('id_card_number',) # 设置身份证号为只读字段
form = UcUserInfoForm # 设置使用自定义表单
def custom_link(self, obj):
# 为每个用户添加自定义链接
url = reverse('all_info_form', args=[obj.pk]) # 生成链接
return format_html('<a href="{}">查看</a>', url) # 创建 HTML 链接
custom_link.short_description = '详细信息' # 设置列标题
admin.site.register(Subject)
admin.site.register(SchoolInfo)

6
ec_user/apps.py Normal file
View File

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

88
ec_user/forms.py Normal file
View File

@ -0,0 +1,88 @@
from django import forms
from .models import EcUser, ContactInfo, SchoolInfo, AcademicInfo, HealthInfo, SelfEvaluation
from .models import HobbiesInterests, SocialPractice, FamilyInfo, AwardsPunishments
class BaiscInfoForm(forms.ModelForm):
class Meta:
model = EcUser
fields = ['name', 'gender', 'age', 'ethnicity', 'dob', 'id_card_number', 'political_status']
class ContactInfoForm(forms.ModelForm):
class Meta:
model = ContactInfo
fields = ['home_address', 'parent_contact', 'student_contact', 'email']
# SchoolInfo 表单
class SchoolInfoForm(forms.ModelForm):
class Meta:
model = SchoolInfo
fields = ['school_name', 'grade', 'class_name', 'admission_date', 'expected_graduation_date']
# AcademicInfo 表单
class AcademicInfoForm(forms.ModelForm):
class Meta:
model = AcademicInfo
fields = ['last_semester_score', 'this_semester_score', 'class_ranking', 'strong_subject', 'weak_subject']
# HealthInfo 表单
class HealthInfoForm(forms.ModelForm):
class Meta:
model = HealthInfo
fields = ['height', 'weight', 'blood_type', 'medical_history', 'disability_status', 'disability_category', 'disability_grade']
# SelfEvaluation 表单
class SelfEvaluationForm(forms.ModelForm):
class Meta:
model = SelfEvaluation
fields = ['strengths', 'weaknesses', 'study_attitude', 'future_plans']
# HobbiesInterests 表单
class HobbiesInterestsForm(forms.ModelForm):
class Meta:
model = HobbiesInterests
fields = ['interests', 'extracurricular_activities']
# SocialPractice 表单
class SocialPracticeForm(forms.ModelForm):
class Meta:
model = SocialPractice
fields = ['activity_name', 'activity_date', 'activity_location', 'activity_description', 'activity_outcome']
# FamilyInfo 表单
class FamilyInfoForm(forms.ModelForm):
class Meta:
model = FamilyInfo
fields = ['family_member', 'economic_status']
# AwardsPunishments 表单
class AwardsPunishmentsForm(forms.ModelForm):
class Meta:
model = AwardsPunishments
fields = ['award_name', 'award_date', 'award_organization', 'discipline_date', 'discipline_issue', 'discipline_outcome']
# 获取或创建各个信息模型实例
g_models = {
'contact_info': ContactInfo,
'school_info': SchoolInfo,
'academic_info': AcademicInfo,
'health_info': HealthInfo,
'self_evaluation': SelfEvaluation,
'hobbies_interests': HobbiesInterests,
'social_practice': SocialPractice,
'family_info': FamilyInfo,
'awards_punishments': AwardsPunishments
}
g_form_classes = {
'contact_info_form': ContactInfoForm,
'school_info_form': SchoolInfoForm,
'academic_info_form': AcademicInfoForm,
'health_info_form': HealthInfoForm,
'self_evaluation_form': SelfEvaluationForm,
'hobbies_interests_form': HobbiesInterestsForm,
'social_practice_form': SocialPracticeForm,
'family_info_form': FamilyInfoForm,
'awards_punishments_form': AwardsPunishmentsForm
}

View File

@ -0,0 +1,155 @@
# Generated by Django 4.2.19 on 2025-02-25 02:55
from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='EcUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('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')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('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')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('name', models.CharField(max_length=100)),
('gender', models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('O', 'Other')], default='M', max_length=1)),
('ethnicity', models.CharField(default='Unknown', max_length=50)),
('dob', models.DateField(blank=True, null=True)),
('id_card_number', models.CharField(max_length=18, unique=True)),
('political_status', models.CharField(default='Unknown', max_length=50)),
('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': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='SocialPractice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('activity_name', models.CharField(max_length=100)),
('activity_date', models.DateField()),
('activity_location', models.CharField(max_length=255)),
('activity_description', models.TextField()),
('activity_outcome', models.TextField()),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='SelfEvaluation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('strengths', models.TextField()),
('weaknesses', models.TextField()),
('study_attitude', models.TextField()),
('future_plans', models.TextField()),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='SchoolInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('school_name', models.CharField(max_length=255)),
('grade', models.CharField(max_length=50)),
('class_name', models.CharField(max_length=50)),
('admission_date', models.DateField()),
('expected_graduation_date', models.DateField()),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='HobbiesInterests',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('interests', models.TextField()),
('extracurricular_activities', models.TextField()),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='HealthInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('height', models.DecimalField(decimal_places=2, max_digits=5)),
('weight', models.DecimalField(decimal_places=2, max_digits=5)),
('blood_type', models.CharField(max_length=3)),
('medical_history', models.TextField(blank=True, null=True)),
('disability_status', models.BooleanField()),
('disability_category', models.CharField(blank=True, max_length=50, null=True)),
('disability_grade', models.CharField(blank=True, max_length=50, null=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='FamilyInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('family_member', models.JSONField()),
('economic_status', models.CharField(max_length=50)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='ContactInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('home_address', models.CharField(max_length=255)),
('parent_contact', models.CharField(max_length=15)),
('student_contact', models.CharField(max_length=15)),
('email', models.EmailField(max_length=254)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='AwardsPunishments',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('award_name', models.CharField(max_length=100)),
('award_date', models.DateField()),
('award_organization', models.CharField(max_length=100)),
('discipline_date', models.DateField(blank=True, null=True)),
('discipline_issue', models.CharField(blank=True, max_length=255, null=True)),
('discipline_outcome', models.CharField(blank=True, max_length=255, null=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='AcademicInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('last_semester_score', models.DecimalField(decimal_places=2, max_digits=5)),
('this_semester_score', models.DecimalField(decimal_places=2, max_digits=5)),
('class_ranking', models.IntegerField()),
('strong_subject', models.CharField(max_length=50)),
('weak_subject', models.CharField(max_length=50)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2.19 on 2025-02-25 03:28
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='socialpractice',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,40 @@
# Generated by Django 4.2.19 on 2025-02-25 04:22
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0002_alter_socialpractice_user'),
]
operations = [
migrations.AlterField(
model_name='awardspunishments',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='familyinfo',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='hobbiesinterests',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='schoolinfo',
name='admission_date',
field=models.DateField(blank=True, null=True),
),
migrations.AlterField(
model_name='schoolinfo',
name='expected_graduation_date',
field=models.DateField(blank=True, null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.19 on 2025-02-25 04:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0003_alter_awardspunishments_user_alter_familyinfo_user_and_more'),
]
operations = [
migrations.AlterField(
model_name='academicinfo',
name='last_semester_score',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AlterField(
model_name='academicinfo',
name='this_semester_score',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-25 04:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0004_alter_academicinfo_last_semester_score_and_more'),
]
operations = [
migrations.AlterField(
model_name='academicinfo',
name='class_ranking',
field=models.IntegerField(blank=True, null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.19 on 2025-02-25 04:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0005_alter_academicinfo_class_ranking'),
]
operations = [
migrations.AlterField(
model_name='healthinfo',
name='height',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AlterField(
model_name='healthinfo',
name='weight',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-25 04:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0006_alter_healthinfo_height_alter_healthinfo_weight'),
]
operations = [
migrations.AlterField(
model_name='healthinfo',
name='disability_status',
field=models.BooleanField(blank=True, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-25 05:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0007_alter_healthinfo_disability_status'),
]
operations = [
migrations.AlterField(
model_name='familyinfo',
name='family_member',
field=models.JSONField(blank=True, null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.19 on 2025-02-25 14:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0008_alter_familyinfo_family_member'),
]
operations = [
migrations.AlterField(
model_name='academicinfo',
name='last_semester_score',
field=models.JSONField(blank=True, null=True),
),
migrations.AlterField(
model_name='academicinfo',
name='this_semester_score',
field=models.JSONField(blank=True, null=True),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.19 on 2025-02-26 03:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0009_alter_academicinfo_last_semester_score_and_more'),
]
operations = [
migrations.CreateModel(
name='Subject',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
],
),
migrations.AddField(
model_name='ecuser',
name='subjects',
field=models.ManyToManyField(blank=True, related_name='users', to='ec_user.subject'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-26 04:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0010_subject_ecuser_subjects'),
]
operations = [
migrations.AddField(
model_name='ecuser',
name='subject_usage_count',
field=models.IntegerField(default=0),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-02-27 11:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ec_user', '0011_ecuser_subject_usage_count'),
]
operations = [
migrations.AddField(
model_name='ecuser',
name='age',
field=models.IntegerField(blank=True, null=True),
),
]

View File

244
ec_user/models.py Normal file
View File

@ -0,0 +1,244 @@
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
from django.db import models
"""
1. UserProfile用户扩展信息表继承AbstractUser
name: 姓名
gender: 性别
ethnicity: 民族
dob: 出生日期
id_card_number: 身份证号码
political_status: 政治面貌
2. ContactInfo联系方式表
user: 外键关联到 UserProfile
home_address: 家庭住址
parent_contact: 家长联系电话
student_contact: 本人联系电话
email: 电子邮箱
3. SchoolInfo就读信息表
user: 外键关联到 UserProfile
school_name: 学校名称
grade: 年级
class: 班级
admission_date: 入学时间
expected_graduation_date: 预计毕业时间
4. AcademicInfo学习情况表
user: 外键关联到 UserProfile
last_semester_score: 上学期期末成绩
this_semester_score: 本学期期中成绩
class_ranking: 班级排名
strong_subject: 特长学科
weak_subject: 薄弱学科
5. FamilyInfo家庭情况表
user: 外键关联到 UserProfile
family_member: 家庭成员信息可以是多个外键或 JSON 字段来存储
economic_status: 家庭经济状况是否低保是否建档立卡等
6. AwardsPunishments奖惩情况表
user: 外键关联到 UserProfile
award_name: 奖项名称
award_date: 奖项颁发时间
award_organization: 奖项颁发单位
discipline_date: 违纪时间
discipline_issue: 违纪事由
discipline_outcome: 处理结果
7. HealthInfo健康状况表
user: 外键关联到 UserProfile
height: 身高
weight: 体重
blood_type: 血型
medical_history: 既往病史重大疾病过敏史等
disability_status: 是否残疾
disability_category: 残疾类别
disability_grade: 残疾等级
8. HobbiesInterests兴趣爱好表
user: 外键关联到 UserProfile
interests: 兴趣爱好如阅读绘画等
extracurricular_activities: 参加的社团或课外兴趣班
9. SocialPractice社会实践表
user: 外键关联到 UserProfile
activity_name: 活动名称
activity_date: 活动时间
activity_location: 活动地点
activity_description: 活动内容
activity_outcome: 活动收获
10. SelfEvaluation自我评价表
user: 外键关联到 UserProfile
strengths: 优点
weaknesses: 不足
study_attitude: 学习态度
future_plans: 未来规划
"""
class Subject(models.Model):
name = models.CharField(max_length=100) # 科目名称
def __str__(self):
return self.name
# EcUser用户表
class EcUser(AbstractUser):
GENDER_CHOICES = [
('M', 'Male'),
('F', 'Female'),
('O', 'Other'),
]
name = models.CharField(max_length=100)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default='M') # 默认值设置为'M'
age = models.IntegerField(null=True, blank=True) # 允许为空可以为null
ethnicity = models.CharField(max_length=50, default='Unknown') # 默认值设置为'Unknown'
dob = models.DateField(null=True, blank=True) # 允许为空可以为null
id_card_number = models.CharField(max_length=18, unique=True)
political_status = models.CharField(max_length=50, default='Unknown') # 默认值设置为'Unknown'
# 多选字段:开放权限的科目
subjects = models.ManyToManyField(Subject, related_name='users', blank=True) # 允许为空,表示可以选择多个科目
# 使用次数限制
subject_usage_count = models.IntegerField(default=0)
def __str__(self):
return self.name
# ContactInfo联系方式表
class ContactInfo(models.Model):
user = models.OneToOneField(EcUser, on_delete=models.CASCADE)
home_address = models.CharField(max_length=255)
parent_contact = models.CharField(max_length=15)
student_contact = models.CharField(max_length=15)
email = models.EmailField()
def __str__(self):
return f"Contact Info of {self.user.name}"
# SchoolInfo就读信息表
class SchoolInfo(models.Model):
user = models.OneToOneField(EcUser, on_delete=models.CASCADE)
school_name = models.CharField(max_length=255)
grade = models.CharField(max_length=50)
class_name = models.CharField(max_length=50) # Changed 'class' to 'class_name' to avoid conflict
admission_date = models.DateField(null=True, blank=True)
expected_graduation_date = models.DateField(null=True, blank=True)
def __str__(self):
return f"School Info of {self.user.name}"
# AcademicInfo学习情况表
class AcademicInfo(models.Model):
user = models.OneToOneField(EcUser, on_delete=models.CASCADE)
# last_semester_score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
# this_semester_score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
last_semester_score = models.JSONField(null=True, blank=True)
this_semester_score = models.JSONField(null=True, blank=True)
class_ranking = models.IntegerField(null=True, blank=True)
strong_subject = models.CharField(max_length=50)
weak_subject = models.CharField(max_length=50)
def __str__(self):
return f"Academic Info of {self.user.name}"
# HealthInfo健康状况表
class HealthInfo(models.Model):
user = models.OneToOneField(EcUser, on_delete=models.CASCADE)
height = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
weight = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
blood_type = models.CharField(max_length=3)
medical_history = models.TextField(null=True, blank=True)
disability_status = models.BooleanField(null=True, blank=True)
disability_category = models.CharField(max_length=50, null=True, blank=True)
disability_grade = models.CharField(max_length=50, null=True, blank=True)
def __str__(self):
return f"Health Info of {self.user.name}"
# SelfEvaluation自我评价表
class SelfEvaluation(models.Model):
user = models.OneToOneField(EcUser, on_delete=models.CASCADE)
strengths = models.TextField()
weaknesses = models.TextField()
study_attitude = models.TextField()
future_plans = models.TextField()
def __str__(self):
return f"Self Evaluation of {self.user.name}"
# HobbiesInterests兴趣爱好表
class HobbiesInterests(models.Model):
# 定义一个与EcUser一对多关联的外键
user = models.ForeignKey(EcUser, on_delete=models.CASCADE)
# 定义一个文本字段,用于存储用户的兴趣爱好
interests = models.TextField()
# 定义一个文本字段,用于存储用户的课外活动
extracurricular_activities = models.TextField()
def __str__(self):
# 返回用户的名字和兴趣爱好
return f"Hobbies and Interests of {self.user.name}"
# SocialPractice社会实践表
class SocialPractice(models.Model):
# 定义一个与EcUser一对多关联的外键
user = models.ForeignKey(EcUser, on_delete=models.CASCADE)
# 定义一个活动名称的字符型字段最大长度为100
activity_name = models.CharField(max_length=100)
# 定义一个活动日期的日期型字段
activity_date = models.DateField()
# 定义一个活动地点的字符型字段最大长度为255
activity_location = models.CharField(max_length=255)
# 定义一个活动描述的文本型字段
activity_description = models.TextField()
# 定义一个活动结果的文本型字段
activity_outcome = models.TextField()
def __str__(self):
# 返回一个字符串,表示该社交实践的用户名称
return f"Social Practice of {self.user.name}"
# FamilyInfo家庭情况表
class FamilyInfo(models.Model):
# 定义一个与EcUser一对多关联的外键
user = models.ForeignKey(EcUser, on_delete=models.CASCADE)
family_member = models.JSONField(null=True, blank=True) # Store family member info as JSON or use a related model for complex relationships
economic_status = models.CharField(max_length=50)
def __str__(self):
x = {
"members": [
{"relationship": "Father", "name": "John", "age": 45, "occupation": "Engineer"},
{"relationship": "Mother", "name": "Jane", "age": 43, "occupation": "Doctor"},
{"relationship": "Brother", "name": "Mike", "age": 20, "occupation": "Student"}
]
}
return f"Family Info of {self.user.name}"
# AwardsPunishments奖惩情况表
class AwardsPunishments(models.Model):
# 定义一个与EcUser一对多关联的外键
user = models.ForeignKey(EcUser, on_delete=models.CASCADE)
award_name = models.CharField(max_length=100)
award_date = models.DateField()
award_organization = models.CharField(max_length=100)
discipline_date = models.DateField(null=True, blank=True)
discipline_issue = models.CharField(max_length=255, null=True, blank=True)
discipline_outcome = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return f"Awards and Punishments of {self.user.name}"

View File

@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>All Information Form</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0-alpha1/css/bootstrap.min.css">
<style>
body {
background-color: #f4f4f9;
font-family: Arial, sans-serif;
}
.container {
max-width: 900px;
}
.form-section {
background-color: #ffffff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.form-section h4 {
font-size: 1.25rem;
color: #333;
margin-bottom: 20px;
}
.form-section .border {
border: 1px solid #e0e0e0;
border-radius: 8px;
}
.form-section .mb-3 {
margin-bottom: 15px;
}
.form-section .form-control {
border-radius: 6px;
}
.btn-submit {
background-color: #007bff;
color: #fff;
border: none;
padding: 12px 30px;
font-size: 16px;
border-radius: 6px;
width: 100%;
}
.btn-submit:hover {
background-color: #0056b3;
cursor: pointer;
}
.empty-message {
color: #888;
font-size: 1rem;
text-align: center;
}
.alert {
margin-top: 20px;
padding: 15px;
}
/* 优化 textarea 的样式 */
textarea {
height: 150px; /* 设置合适的高度 */
resize: vertical; /* 只允许垂直调整大小 */
padding: 10px; /* 设置内边距,增加可读性 */
}
/* 如果 textarea 太长,可以设置最大高度 */
textarea {
width: 100%; /* 设置最大高度,避免过高 */
}
</style>
</head>
<body>
{% extends 'admin/base_site.html' %}
<!-- {% block title %}
{{ admin_site.site_title }} - {{ user.username }}'s Profile
{% endblock %} -->
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">诊断应用后台</a></h1>
{% endblock %}
{% block content %}
<div class="container mt-5">
<h2 class="text-center mb-4">填写信息 - {{ user.name }}</h2>
<form method="POST">
<!-- 联系方式 -->
<div class="form-section">
<h4>联系方式</h4>
{{ contact_info_form.as_p }}
</div>
<!-- 就读信息 -->
<div class="form-section">
<h4>就读信息</h4>
{{ school_info_form.as_p }}
</div>
<!-- 学习情况 -->
<div class="form-section">
<h4>学习情况</h4>
<div id="gradeForm" style="border: 1px solid #ccc; padding: 10px;">
<div class="form-group">
<label for="subject1">语文</label>
<input type="text" id="subject1" name="subject1">
</div>
<div class="form-group">
<label for="subject2">数学</label>
<input type="text" id="subject2" name="subject2">
</div>
<div class="form-group">
<label for="subject3">英语</label>
<input type="text" id="subject3" name="subject3">
</div>
<div class="form-group">
<label for="subject4">物理</label>
<input type="text" id="subject4" name="subject4">
</div>
<div class="form-group">
<label for="subject5">化学</label>
<input type="text" id="subject5" name="subject5">
</div>
<div class="form-group">
<label for="subject6">生物</label>
<input type="text" id="subject6" name="subject6">
</div>
<div class="form-group">
<label for="subject7">历史</label>
<input type="text" id="subject7" name="subject7">
</div>
<div class="form-group">
<label for="subject8">地理</label>
<input type="text" id="subject8" name="subject8">
</div>
<div class="form-group">
<label for="subject9">政治</label>
<input type="text" id="subject9" name="subject9">
</div>
<div style="margin-top: 10px;">
<div id="grades_parse_result">生成json字符串{}</div>
<button type="button" id="parseGrades" class="btn btn-primary">解析成绩</button>
<div>
<label for="json_encoded_grades">输入json字符串</label>
<input type="text" id="json_encoded_grades" name="json_encoded_grades">
</div>
<button type="button" id="showGrades" class="btn btn-primary">展示成绩</button>
</div>
<script>
document.getElementById('parseGrades').addEventListener('click', function(event) {
// 获取所有科目的成绩输入框
const subjects = ['subject1', 'subject2', 'subject3', 'subject4', 'subject5', 'subject6', 'subject7', 'subject8', 'subject9']
let grades = {}
let atLeastOneFilled = false
// 获取每个科目的成绩,检查是否有至少一项成绩填写
subjects.forEach(subject => {
const grade = document.getElementById(subject).value.trim()
if (grade) {
grades[subject] = grade
atLeastOneFilled = true
}
});
// 检查是否至少填写了一项成绩
if (!atLeastOneFilled) {
alert("至少填写一门成绩!")
return
}
// 将成绩数据转换为 JSON 格式
const jsonGrades = JSON.stringify(grades)
// 发送数据到后台(你可以修改为你自己的后台 API
console.log("成绩数据:", jsonGrades)
document.getElementById('grades_parse_result').innerHTML = `生成json字符串${jsonGrades}`
navigator.clipboard.writeText(jsonGrades).then(function() {
alert("文本已复制到剪贴板!");
}).catch(function(err) {
alert("复制失败: " + err);
});
});
document.getElementById('showGrades').addEventListener('click', function(event) {
// 获取 JSON 格式的成绩数据
const jsonGrades = document.getElementById('json_encoded_grades').value.trim()
if (!jsonGrades) {
alert("请输入 JSON 格式的成绩数据!")
return
}
// 解析 JSON 数据
const grades = JSON.parse(jsonGrades)
const subjects = ['subject1', 'subject2', 'subject3', 'subject4', 'subject5', 'subject6', 'subject7', 'subject8', 'subject9']
// 遍历每个科目,填充相应的成绩
subjects.forEach(subject => {
if (grades[subject]) {
document.getElementById(subject).value = grades[subject] // 填充成绩数据
}
})
})
</script>
</div>
{{ academic_info_form.as_p }}
</div>
<!-- 健康状况 -->
<div class="form-section">
<h4>健康状况</h4>
{{ health_info_form.as_p }}
</div>
<!-- 自我评价 -->
<div class="form-section">
<h4>自我评价</h4>
{{ self_evaluation_form.as_p }}
</div>
<button type="submit" class="btn-submit">提交</button>
</form>
<form method="POST" action="/ec_user/all_info_edit/{{ user.id }}/hobbies_interests/">
<!-- 兴趣爱好 -->
<div class="form-section">
<h4>兴趣爱好</h4>
{{ hobbies_interests_form.management_form }} <!-- 管理表单 -->
{% for form in hobbies_interests_form %}
<div class="border p-3 mb-3">
{{ form.as_p }}
</div>
{% empty %}
<p class="empty-message">没有兴趣爱好信息。</p>
{% endfor %}
<button type="submit" class="btn-submit">提交</button>
</div>
</form>
<form method="POST" action="/ec_user/all_info_edit/{{ user.id }}/social_practice/">
<!-- 社会实践 -->
<div class="form-section">
<h4>社会实践</h4>
{{ social_practice_form.management_form }}
{% for form in social_practice_form %}
<div class="border p-3 mb-3">
{{ form.as_p }}
</div>
{% empty %}
<p class="empty-message">没有社会实践记录。</p>
{% endfor %}
<button type="submit" class="btn-submit">提交</button>
</div>
</form>
<form method="POST" action="/ec_user/all_info_edit/{{ user.id }}/family_info/">
<!-- 家庭情况 -->
<div class="form-section">
<h4>家庭情况</h4>
{{ family_info_form.management_form }}
{% for form in family_info_form %}
<div class="border p-3 mb-3">
{{ form.as_p }}
</div>
{% empty %}
<p class="empty-message">没有家庭情况记录。</p>
{% endfor %}
<button type="submit" class="btn-submit">提交</button>
</div>
</form>
<form method="POST" action="/ec_user/all_info_edit/{{ user.id }}/awards_punishments/" >
<!-- 奖惩情况 -->
<div class="form-section">
<h4>奖惩情况</h4>
{{ awards_punishments_form.management_form }}
{% for form in awards_punishments_form %}
<div class="border p-3 mb-3">
{{ form.as_p }}
</div>
{% empty %}
<p class="empty-message">没有奖惩情况记录。</p>
{% endfor %}
<button type="submit" class="btn-submit">提交</button>
</div>
</form>
</div>
{% endblock %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,9 @@
<p>
注意管理员实际不应直接修改用户数据
</p>
<p>
对id为 {{ user.id }} 的用户进行了修改。
{{ formset.errors }}
修改了 {{ model_name }} 的信息。
</p>

View File

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Academic Info API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Academic Info API</h2>
<h3>Get Academic Info</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getAcademicInfo()">Get Academic Info</button>
<div id="get-result" class="message"></div>
<h3>Update Academic Info</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="last_semester_score">Last Semester Score:</label>
<input type="number" id="last_semester_score" placeholder="Enter last semester score" step="0.01">
<br><br>
<label for="this_semester_score">This Semester Score:</label>
<input type="number" id="this_semester_score" placeholder="Enter this semester score" step="0.01">
<br><br>
<label for="class_ranking">Class Ranking:</label>
<input type="number" id="class_ranking" placeholder="Enter class ranking">
<br><br>
<label for="strong_subject">Strong Subject:</label>
<input type="text" id="strong_subject" placeholder="Enter strong subject">
<br><br>
<label for="weak_subject">Weak Subject:</label>
<input type="text" id="weak_subject" placeholder="Enter weak subject">
<br><br>
<button onclick="updateAcademicInfo()">Update Academic Info</button>
<div id="post-result" class="message"></div>
<script>
// Function to get academic info via GET request
function getAcademicInfo() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/academic_info/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `Last Semester Score: ${data.last_semester_score}, This Semester Score: ${data.this_semester_score}, Class Ranking: ${data.class_ranking}, Strong Subject: ${data.strong_subject}, Weak Subject: ${data.weak_subject}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update academic info via POST request
function updateAcademicInfo() {
const userId = document.getElementById('user_id_post').value;
const lastSemesterScore = document.getElementById('last_semester_score').value;
const thisSemesterScore = document.getElementById('this_semester_score').value;
const classRanking = document.getElementById('class_ranking').value;
const strongSubject = document.getElementById('strong_subject').value;
const weakSubject = document.getElementById('weak_subject').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !lastSemesterScore || !thisSemesterScore || !classRanking || !strongSubject || !weakSubject) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
last_semester_score: lastSemesterScore,
this_semester_score: thisSemesterScore,
class_ranking: classRanking,
strong_subject: strongSubject,
weak_subject: weakSubject
};
fetch(`/ec_user/academic_info/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Awards and Punishments API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Awards and Punishments API</h2>
<h3>Get Awards and Punishments</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getAwardsPunishments()">Get Awards and Punishments</button>
<div id="get-result" class="message"></div>
<h3>Update Awards and Punishments</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="award_name">Award Name:</label>
<input type="text" id="award_name" placeholder="Enter award name">
<br><br>
<label for="award_date">Award Date:</label>
<input type="date" id="award_date">
<br><br>
<label for="award_organization">Award Organization:</label>
<input type="text" id="award_organization" placeholder="Enter award organization">
<br><br>
<label for="discipline_date">Discipline Date (optional):</label>
<input type="date" id="discipline_date">
<br><br>
<label for="discipline_issue">Discipline Issue (optional):</label>
<input type="text" id="discipline_issue" placeholder="Enter discipline issue">
<br><br>
<label for="discipline_outcome">Discipline Outcome (optional):</label>
<input type="text" id="discipline_outcome" placeholder="Enter discipline outcome">
<br><br>
<button onclick="updateAwardsPunishments()">Update Awards and Punishments</button>
<div id="post-result" class="message"></div>
<script>
// Function to get awards and punishments via GET request
function getAwardsPunishments() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/awards_punishments/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = JSON.stringify(data, null, 2);
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update awards and punishments via POST request
function updateAwardsPunishments() {
const userId = document.getElementById('user_id_post').value;
const awardName = document.getElementById('award_name').value;
const awardDate = document.getElementById('award_date').value;
const awardOrganization = document.getElementById('award_organization').value;
const disciplineDate = document.getElementById('discipline_date').value;
const disciplineIssue = document.getElementById('discipline_issue').value;
const disciplineOutcome = document.getElementById('discipline_outcome').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !awardName || !awardDate || !awardOrganization) {
resultDiv.textContent = "Please fill out all required fields.";
return;
}
const postData = {
award_name: awardName,
award_date: awardDate,
award_organization: awardOrganization,
discipline_date: disciplineDate || null,
discipline_issue: disciplineIssue || null,
discipline_outcome: disciplineOutcome || null
};
fetch(`/ec_user/awards_punishments/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Contact Info API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Contact Info API</h2>
<h3>Get Contact Info</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getContactInfo()">Get Contact Info</button>
<div id="get-result" class="message"></div>
<h3>Update Contact Info</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="home_address">Home Address:</label>
<input type="text" id="home_address" placeholder="Enter home address">
<br><br>
<label for="parent_contact">Parent Contact:</label>
<input type="text" id="parent_contact" placeholder="Enter parent contact">
<br><br>
<label for="student_contact">Student Contact:</label>
<input type="text" id="student_contact" placeholder="Enter student contact">
<br><br>
<label for="email">Email:</label>
<input type="email" id="email" placeholder="Enter email">
<br><br>
<button onclick="updateContactInfo()">Update Contact Info</button>
<div id="post-result" class="message"></div>
<script>
// Function to get contact info via GET request
function getContactInfo() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/contact_info/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `Home Address: ${data.home_address}, Parent Contact: ${data.parent_contact}, Student Contact: ${data.student_contact}, Email: ${data.email}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update contact info via POST request
function updateContactInfo() {
const userId = document.getElementById('user_id_post').value;
const homeAddress = document.getElementById('home_address').value;
const parentContact = document.getElementById('parent_contact').value;
const studentContact = document.getElementById('student_contact').value;
const email = document.getElementById('email').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !homeAddress || !parentContact || !studentContact || !email) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
home_address: homeAddress,
parent_contact: parentContact,
student_contact: studentContact,
email: email
};
fetch(`/ec_user/contact_info/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Family Info API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Family Info API</h2>
<h3>Get Family Info</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getFamilyInfo()">Get Family Info</button>
<div id="get-result" class="message"></div>
<h3>Update Family Info</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="family_member">Family Members (JSON format):</label>
<textarea id="family_member" placeholder='Enter family member info as JSON (e.g., [{"name": "John", "relationship": "Father"}])'></textarea>
<br><br>
<label for="economic_status">Economic Status:</label>
<input type="text" id="economic_status" placeholder="Enter economic status">
<br><br>
<button onclick="updateFamilyInfo()">Update Family Info</button>
<div id="post-result" class="message"></div>
<script>
// Function to get family info via GET request
function getFamilyInfo() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/family_info/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `Family Members: ${JSON.stringify(data.family_member)}, Economic Status: ${data.economic_status}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update family info via POST request
function updateFamilyInfo() {
const userId = document.getElementById('user_id_post').value;
const familyMember = document.getElementById('family_member').value;
const economicStatus = document.getElementById('economic_status').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !familyMember || !economicStatus) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
try {
// Convert the family_member field to JSON
const familyMemberJSON = JSON.parse(familyMember);
const postData = {
family_member: familyMemberJSON,
economic_status: economicStatus
};
fetch(`/ec_user/family_info/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
} catch (error) {
resultDiv.textContent = "Invalid JSON format for family members.";
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Health Info API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Health Info API</h2>
<h3>Get Health Info</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getHealthInfo()">Get Health Info</button>
<div id="get-result" class="message"></div>
<h3>Update Health Info</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="height">Height:</label>
<input type="number" id="height" placeholder="Enter height" step="0.01">
<br><br>
<label for="weight">Weight:</label>
<input type="number" id="weight" placeholder="Enter weight" step="0.01">
<br><br>
<label for="blood_type">Blood Type:</label>
<input type="text" id="blood_type" placeholder="Enter blood type">
<br><br>
<label for="medical_history">Medical History:</label>
<textarea id="medical_history" placeholder="Enter medical history"></textarea>
<br><br>
<label for="disability_status">Disability Status:</label>
<input type="checkbox" id="disability_status">
<br><br>
<label for="disability_category">Disability Category:</label>
<input type="text" id="disability_category" placeholder="Enter disability category">
<br><br>
<label for="disability_grade">Disability Grade:</label>
<input type="text" id="disability_grade" placeholder="Enter disability grade">
<br><br>
<button onclick="updateHealthInfo()">Update Health Info</button>
<div id="post-result" class="message"></div>
<script>
// Function to get health info via GET request
function getHealthInfo() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/health_info/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `Height: ${data.height}, Weight: ${data.weight}, Blood Type: ${data.blood_type}, Medical History: ${data.medical_history}, Disability Status: ${data.disability_status}, Disability Category: ${data.disability_category}, Disability Grade: ${data.disability_grade}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update health info via POST request
function updateHealthInfo() {
const userId = document.getElementById('user_id_post').value;
const height = document.getElementById('height').value;
const weight = document.getElementById('weight').value;
const bloodType = document.getElementById('blood_type').value;
const medicalHistory = document.getElementById('medical_history').value;
const disabilityStatus = document.getElementById('disability_status').checked;
const disabilityCategory = document.getElementById('disability_category').value;
const disabilityGrade = document.getElementById('disability_grade').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !height || !weight || !bloodType) {
resultDiv.textContent = "Please fill out all required fields.";
return;
}
const postData = {
height: height,
weight: weight,
blood_type: bloodType,
medical_history: medicalHistory,
disability_status: disabilityStatus,
disability_category: disabilityCategory,
disability_grade: disabilityGrade
};
fetch(`/ec_user/health_info/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Hobbies and Interests API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Hobbies and Interests API</h2>
<h3>Get Hobbies and Interests</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getHobbiesInterests()">Get Hobbies and Interests</button>
<div id="get-result" class="message"></div>
<h3>Add Hobbies and Interests</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="interests">Interests:</label>
<textarea id="interests" placeholder="Enter interests"></textarea>
<br><br>
<label for="extracurricular_activities">Extracurricular Activities:</label>
<textarea id="extracurricular_activities" placeholder="Enter extracurricular activities"></textarea>
<br><br>
<button onclick="addHobbiesInterests()">Add Hobbies and Interests</button>
<div id="post-result" class="message"></div>
<script>
// Function to get hobbies and interests via GET request
function getHobbiesInterests() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/hobbies_interests/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
let resultText = '';
data.forEach(entry => {
resultText += `Interests: ${entry.interests}, Extracurricular Activities: ${entry.extracurricular_activities}<br>`;
});
resultDiv.innerHTML = resultText;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to add hobbies and interests via POST request
function addHobbiesInterests() {
const userId = document.getElementById('user_id_post').value;
const interests = document.getElementById('interests').value;
const extracurricularActivities = document.getElementById('extracurricular_activities').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !interests || !extracurricularActivities) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
interests: interests,
extracurricular_activities: extracurricularActivities
};
fetch(`/ec_user/hobbies_interests/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test School Info API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test School Info API</h2>
<h3>Get School Info</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getSchoolInfo()">Get School Info</button>
<div id="get-result" class="message"></div>
<h3>Update School Info</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="school_name">School Name:</label>
<input type="text" id="school_name" placeholder="Enter school name">
<br><br>
<label for="grade">Grade:</label>
<input type="text" id="grade" placeholder="Enter grade">
<br><br>
<label for="class_name">Class Name:</label>
<input type="text" id="class_name" placeholder="Enter class name">
<br><br>
<label for="admission_date">Admission Date:</label>
<input type="date" id="admission_date">
<br><br>
<label for="expected_graduation_date">Expected Graduation Date:</label>
<input type="date" id="expected_graduation_date">
<br><br>
<button onclick="updateSchoolInfo()">Update School Info</button>
<div id="post-result" class="message"></div>
<script>
// Function to get school info via GET request
function getSchoolInfo() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/school_info/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `School Name: ${data.school_name}, Grade: ${data.grade}, Class Name: ${data.class_name}, Admission Date: ${data.admission_date}, Expected Graduation Date: ${data.expected_graduation_date}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update school info via POST request
function updateSchoolInfo() {
const userId = document.getElementById('user_id_post').value;
const schoolName = document.getElementById('school_name').value;
const grade = document.getElementById('grade').value;
const className = document.getElementById('class_name').value;
const admissionDate = document.getElementById('admission_date').value;
const expectedGraduationDate = document.getElementById('expected_graduation_date').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !schoolName || !grade || !className || !admissionDate || !expectedGraduationDate) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
school_name: schoolName,
grade: grade,
class_name: className,
admission_date: admissionDate,
expected_graduation_date: expectedGraduationDate
};
fetch(`/ec_user/school_info/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Self Evaluation API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Self Evaluation API</h2>
<h3>Get Self Evaluation</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getSelfEvaluation()">Get Self Evaluation</button>
<div id="get-result" class="message"></div>
<h3>Update Self Evaluation</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="strengths">Strengths:</label>
<textarea id="strengths" placeholder="Enter your strengths"></textarea>
<br><br>
<label for="weaknesses">Weaknesses:</label>
<textarea id="weaknesses" placeholder="Enter your weaknesses"></textarea>
<br><br>
<label for="study_attitude">Study Attitude:</label>
<textarea id="study_attitude" placeholder="Enter your study attitude"></textarea>
<br><br>
<label for="future_plans">Future Plans:</label>
<textarea id="future_plans" placeholder="Enter your future plans"></textarea>
<br><br>
<button onclick="updateSelfEvaluation()">Update Self Evaluation</button>
<div id="post-result" class="message"></div>
<script>
// Function to get self evaluation via GET request
function getSelfEvaluation() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/self_evaluation/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = `Strengths: ${data.strengths}, Weaknesses: ${data.weaknesses}, Study Attitude: ${data.study_attitude}, Future Plans: ${data.future_plans}`;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to update self evaluation via POST request
function updateSelfEvaluation() {
const userId = document.getElementById('user_id_post').value;
const strengths = document.getElementById('strengths').value;
const weaknesses = document.getElementById('weaknesses').value;
const studyAttitude = document.getElementById('study_attitude').value;
const futurePlans = document.getElementById('future_plans').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !strengths || !weaknesses || !studyAttitude || !futurePlans) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
strengths: strengths,
weaknesses: weaknesses,
study_attitude: studyAttitude,
future_plans: futurePlans
};
fetch(`/ec_user/self_evaluation/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Social Practice API</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.message {
margin-top: 10px;
padding: 10px;
background-color: #f4f4f4;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h2>Test Social Practice API</h2>
<h3>Get Social Practice Records</h3>
<label for="user_id_get">User ID:</label>
<input type="number" id="user_id_get" min="1" placeholder="Enter user ID">
<button onclick="getSocialPractice()">Get Social Practice Records</button>
<div id="get-result" class="message"></div>
<h3>Add Social Practice Record</h3>
<label for="user_id_post">User ID:</label>
<input type="number" id="user_id_post" min="1" placeholder="Enter user ID">
<br><br>
<label for="activity_name">Activity Name:</label>
<input type="text" id="activity_name" placeholder="Enter activity name">
<br><br>
<label for="activity_date">Activity Date:</label>
<input type="date" id="activity_date">
<br><br>
<label for="activity_location">Activity Location:</label>
<input type="text" id="activity_location" placeholder="Enter activity location">
<br><br>
<label for="activity_description">Activity Description:</label>
<textarea id="activity_description" placeholder="Enter activity description"></textarea>
<br><br>
<label for="activity_outcome">Activity Outcome:</label>
<textarea id="activity_outcome" placeholder="Enter activity outcome"></textarea>
<br><br>
<button onclick="addSocialPractice()">Add Social Practice Record</button>
<div id="post-result" class="message"></div>
<script>
// Function to get social practice records via GET request
function getSocialPractice() {
const userId = document.getElementById('user_id_get').value;
const resultDiv = document.getElementById('get-result');
if (!userId) {
resultDiv.textContent = "Please enter a valid user ID.";
return;
}
fetch(`/ec_user/social_practice/api/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
let resultText = '';
data.forEach(entry => {
resultText += `Activity Name: ${entry.activity_name}, Activity Date: ${entry.activity_date}, Location: ${entry.activity_location}, Description: ${entry.activity_description}, Outcome: ${entry.activity_outcome}<br><br>`;
});
resultDiv.innerHTML = resultText;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
// Function to add a social practice record via POST request
function addSocialPractice() {
const userId = document.getElementById('user_id_post').value;
const activityName = document.getElementById('activity_name').value;
const activityDate = document.getElementById('activity_date').value;
const activityLocation = document.getElementById('activity_location').value;
const activityDescription = document.getElementById('activity_description').value;
const activityOutcome = document.getElementById('activity_outcome').value;
const resultDiv = document.getElementById('post-result');
if (!userId || !activityName || !activityDate || !activityLocation || !activityDescription || !activityOutcome) {
resultDiv.textContent = "Please fill out all fields.";
return;
}
const postData = {
activity_name: activityName,
activity_date: activityDate,
activity_location: activityLocation,
activity_description: activityDescription,
activity_outcome: activityOutcome
};
fetch(`/ec_user/social_practice/api/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': '486ef8198bb10ba6878eba95771c064ff64db81a'
},
body: JSON.stringify(postData)
})
.then(response => response.json())
.then(data => {
if (data.error) {
resultDiv.textContent = `Error: ${data.error}`;
} else {
resultDiv.textContent = data.message;
}
})
.catch(error => {
resultDiv.textContent = `Error: ${error.message}`;
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,12 @@
<a href="/ec_user/api_contact_info_test/"> 联系方式</a>
<a href="/ec_user/api_school_info_test/"> 就读信息</a>
<a href="/ec_user/api_academic_info_test/"> 学习情况</a>
<a href="/ec_user/api_health_info_test/"> 健康状况</a>
<a href="/ec_user/api_self_evaluation_test/"> 自我评价</a>
<a href="/ec_user/api_hobbies_interests_test/"> 兴趣爱好</a>
<a href="/ec_user/api_social_practice_test/"> 社会实践</a>
<a href="/ec_user/api_family_info_test/"> 家庭状况</a>
<a href="/ec_user/api_awards_punishments_test/"> 奖惩情况</a>
<a href="/ec_user/all_info_form/1/"> 信息总览</a>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<script>
</script>
<script>
function hashPassword(password) {
return CryptoJS.SHA256(password).toString();
}
function loginUser() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const data = {
username: username,
password: password
};
fetch('/ec_user/login/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert('Error: ' + data.error);
} else {
alert('Success: ' + data.message);
}
})
.catch((error) => {
console.error('Error:', error);
});
}
</script>
</head>
<body>
<h2>Login</h2>
<form onsubmit="event.preventDefault(); loginUser();">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" required><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" required><br><br>
<input type="submit" value="Login">
</form>
</body>
</html>

3
ec_user/tests.py Normal file
View File

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

58
ec_user/urls.py Normal file
View File

@ -0,0 +1,58 @@
from django.urls import path
from . views import ec_login, MyProtectedUserLogout, index_test
from . views import MyProtectedApiContactInfo, api_contact_info_test, MyProtectedApiSchoolInfo, api_school_info_test
from . views import MyProtectedApiAcademicInfo, api_academic_info_test, MyProtectedApiHealthInfo, api_health_info_test
from . views import MyProtectedApiSelfEvaluationInfo, api_self_evaluation_test, MyProtectedFamilyInfo, api_family_info_test
from . views import MyProtectedApiHobbiesInterests, api_hobbies_interests_test, MyProtectedSocialPractice, api_social_practice_test
from . views import MyProtectedAwardsPunishments, api_awards_punishments_test , MyProtectedBasicUserInfo
from . views import all_info_form, all_info_edit
from . views import MyProtectedUserInfo
urlpatterns = [
path('', index_test, name='index_test'),
path('login/', ec_login, name='login'),
path('logout/', MyProtectedUserLogout.as_view(), name='logout'),
path('contact_info/api/', MyProtectedApiContactInfo.as_view(), name='api_contact_info'),
path('api_contact_info_test/', api_contact_info_test, name='api_contact_info_test'),
path('school_info/api/', MyProtectedApiSchoolInfo.as_view(), name='api_school_info'),
path('api_school_info_test/', api_school_info_test, name='api_school_info_test'),
path('academic_info/api/', MyProtectedApiAcademicInfo.as_view(), name='api_academic_info'),
path('api_academic_info_test/', api_academic_info_test, name='api_academic_info_test'),
path('health_info/api/', MyProtectedApiHealthInfo.as_view(), name='api_health_info'),
path('api_health_info_test/', api_health_info_test, name='api_health_info_test'),
path('self_evaluation/api/', MyProtectedApiSelfEvaluationInfo.as_view(), name='api_self_evaluation'),
path('api_self_evaluation_test/', api_self_evaluation_test, name='api_self_evaluation_test'),
path('hobbies_interests/api/', MyProtectedApiHobbiesInterests.as_view(), name='api_hobbies_interests'),
path('api_hobbies_interests_test/', api_hobbies_interests_test, name='api_hobbies_interests_test'),
path('social_practice/api/', MyProtectedSocialPractice.as_view(), name='api_social_practice'),
path('api_social_practice_test/', api_social_practice_test, name='api_social_practice_test'),
path('family_info/api/', MyProtectedFamilyInfo.as_view(), name='api_family_info'),
path('api_family_info_test/', api_family_info_test, name='api_family_info_test'),
path('awards_punishments/api/', MyProtectedAwardsPunishments.as_view(), name='api_awards_punishments'),
path('api_awards_punishments_test/', api_awards_punishments_test, name='api_awards_punishments_test'),
path('all_info_form/<int:user_id>/', all_info_form, name='all_info_form'),
path('all_info_edit/<int:user_id>/<str:model_name>/', all_info_edit, name='all_info_edit'),
path('api_user_info/', MyProtectedUserInfo.as_view(), name='api_user_info'),
path('basic_user_info/api/', MyProtectedBasicUserInfo.as_view(), name='api_basic_user_info'),
]

659
ec_user/views.py Normal file
View File

@ -0,0 +1,659 @@
from django.http import JsonResponse, HttpResponse
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect
from django.forms import modelformset_factory
from rest_framework.authtoken.models import Token # 导入 Token 模型
import json
from datetime import timedelta
from django.utils import timezone
from authentication.models import CustomToken
from django.contrib.auth.hashers import check_password, make_password # 导入密码哈希比较方法
from .models import EcUser, ContactInfo, SchoolInfo, AcademicInfo, HealthInfo, SelfEvaluation
from .models import HobbiesInterests, SocialPractice, FamilyInfo, AwardsPunishments
from .forms import g_models, g_form_classes
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from authentication.authentication import CustomTokenAuthentication
def index_test(request):
return render(request, 'index.html')
def ec_login(request):
if request.method != 'POST':
return render(request, 'testlogin.html')
try:
data = json.loads(request.body)
username = data.get('username')
password = data.get('password')
except json.JSONDecodeError:
return JsonResponse({'error': 'Invalid JSON'}, status=400)
if not username or not password:
return JsonResponse({'error': 'Missing username or password'}, status=400)
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
# 生成 Token你可以选择使用自定义的 CustomToken
# token, created = Token.objects.get_or_create(user=user) # 使用 DRF 提供的 Token 模型
# 如果你使用的是自定义的 CustomToken
token, created = CustomToken.objects.get_or_create(user=user, defaults={'extra_info': 'your_value', 'expiration_date': timezone.now() + timedelta(days=7)})
if not created:
token.expiration_date = timezone.now() + timedelta(days=7)
token.save()
return JsonResponse({'message': 'Login Success!', 'token': token.key}) # 返回 token
else:
return JsonResponse({'error': 'Login Failed!'}, status=401)
class MyProtectedUserLogout(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
if user.is_authenticated:
# 删除与当前用户相关的 Token
CustomToken.objects.filter(user=user).delete()
# 进行登出操作
logout(request)
return JsonResponse({'message': 'Logout Successful'}, status=200)
else:
return JsonResponse({'error': 'User not authenticated'}, status=400)
def all_info_form(request, user_id):
try:
user = EcUser.objects.get(id=user_id)
except EcUser.DoesNotExist:
return render(request, 'error.html', {"message": "User not found"})
instances = {}
for key, model in g_models.items():
if key in ['hobbies_interests', 'social_practice', 'family_info', 'awards_punishments']:
instances[key] = model.objects.filter(user=user) # 处理一对多关系
else:
instance, _ = model.objects.get_or_create(user=user)
instances[key] = instance
if request.method == 'GET':
# 初始化所有表单
forms = {}
for form_key, form_class in g_form_classes.items():
if form_key in ['hobbies_interests_form', 'social_practice_form', 'family_info_form', 'awards_punishments_form']:
queryset = instances[form_key[:-5]] # 获取对应模型的查询集
# 如果查询集为空,设置 extra=1 来允许添加空表单
if queryset.exists():
formset_class = modelformset_factory(queryset.model, form=form_class, extra=0)
else:
formset_class = modelformset_factory(queryset.model, form=form_class, extra=1)
# 使用 formset 渲染表单
forms[form_key] = formset_class(queryset=queryset)
else:
forms[form_key] = form_class(instance=instances[form_key[:-5]])
return render(request, 'all_info_form.html', {'user': user, **forms})
else:
return HttpResponse("Not implemented")
def all_info_edit(request, user_id, model_name):
try:
user = EcUser.objects.get(id=user_id)
except EcUser.DoesNotExist:
return render(request, 'error.html', {"message": "User not found"})
instances = g_models[model_name].objects.filter(user=user) # 处理一对多关系
print(instances)
formset_class = modelformset_factory(model=g_models[model_name], form=g_form_classes[model_name + '_form'], extra=0)
formset = formset_class(request.POST, queryset=instances)
print(instances)
if formset.is_valid():
instances = formset.save(commit=False)
instances[0].user = user
formset.save()
else:
return render(request, 'all_info_result.html', {'user': user, "model_name": model_name, "formset": formset})
return render(request, 'all_info_result.html', {'user': user, "model_name": model_name, "formset": None})
# ================= API 接口 =================
# +++++++++++++++++++++++++++++++++++++++++++=
class MyProtectedUserInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
# 返回用户的 ID、用户名、剩余次数和主题列表
return JsonResponse({"user_id": request.user.id,
"name": request.user.name,
"username": request.user.username,
"remain_count": request.user.subject_usage_count,
"subject": list(request.user.subjects.values_list('name', flat=True)),
"fill_status":
{
"contact_info": ContactInfo.objects.filter(user=request.user).exists(),
"scholar_info": SchoolInfo.objects.filter(user=request.user).exists(),
"academic_info": AcademicInfo.objects.filter(user=request.user).exists(),
"health_info": HealthInfo.objects.filter(user=request.user).exists(),
"self_evaluation": SelfEvaluation.objects.filter(user=request.user).exists(),
"family_info": FamilyInfo.objects.filter(user=request.user).exists(),
"hobbies_interests": HobbiesInterests.objects.filter(user=request.user).exists(),
"social_practice": SocialPractice.objects.filter(user=request.user).exists(),
"awards_punishments": AwardsPunishments.objects.filter(user=request.user).exists(),
}
})
class MyProtectedBasicUserInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取用户信息并返回 JSON 格式
user_info = EcUser.objects.filter(id=user.id).first()
if user_info:
response_data = {
"name": user_info.name,
"gender": user_info.get_gender_display(),
"age": user_info.age,
"ethnicity": user_info.ethnicity,
"dob": user_info.dob,
"id_card_number": user_info.id_card_number,
"political_status": user_info.political_status
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No user info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户信息
try:
data = json.loads(request.body)
name = data.get("name")
gender = data.get("gender")
age = data.get("age")
ethnicity = data.get("ethnicity")
dob = data.get("dob")
id_card_number = data.get("id_card_number")
political_status = data.get("political_status")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 EcUser
try:
user_info = EcUser.objects.get(id=user.id)
except EcUser.DoesNotExist:
return JsonResponse({"error": "User not found"}, status=404)
# 更新用户信息
user_info.name = name
user_info.gender = gender
user_info.age = age
user_info.ethnicity = ethnicity
user_info.dob = dob
user_info.id_card_number = id_card_number
user_info.political_status = political_status
user_info.save()
return JsonResponse({"message": "User info updated successfully"})
def api_contact_info_test(req):
return render(req, 'api_contact_info_test.html')
class MyProtectedApiContactInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取联系信息并返回 JSON 格式
contact_info = ContactInfo.objects.filter(user=user).first()
if contact_info:
response_data = {
"home_address": contact_info.home_address,
"parent_contact": contact_info.parent_contact,
"student_contact": contact_info.student_contact,
"email": contact_info.email
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No contact info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户的联系信息
try:
data = json.loads(request.body)
home_address = data.get("home_address")
parent_contact = data.get("parent_contact")
student_contact = data.get("student_contact")
email = data.get("email")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 ContactInfo
contact_info, created = ContactInfo.objects.get_or_create(user=user)
contact_info.home_address = home_address
contact_info.parent_contact = parent_contact
contact_info.student_contact = student_contact
contact_info.email = email
contact_info.save()
return JsonResponse({"message": "Contact info updated successfully"})
def api_school_info_test(req):
return render(req, 'api_school_info_test.html')
class MyProtectedApiSchoolInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取学校信息并返回 JSON 格式
school_info = SchoolInfo.objects.filter(user=user).first()
if school_info:
response_data = {
"school_name": school_info.school_name,
"grade": school_info.grade,
"class_name": school_info.class_name,
"admission_date": school_info.admission_date,
"expected_graduation_date": school_info.expected_graduation_date
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No school info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新学校信息
try:
data = json.loads(request.body)
school_name = data.get("school_name")
grade = data.get("grade")
class_name = data.get("class_name")
admission_date = data.get("admission_date")
expected_graduation_date = data.get("expected_graduation_date")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 SchoolInfo
school_info, created = SchoolInfo.objects.get_or_create(user=user)
school_info.school_name = school_name
school_info.grade = grade
school_info.class_name = class_name
school_info.admission_date = admission_date
school_info.expected_graduation_date = expected_graduation_date
school_info.save()
return JsonResponse({"message": "School info updated successfully"})
def api_academic_info_test(req):
return render(req, 'api_academic_info_test.html')
class MyProtectedApiAcademicInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取学习情况信息并返回 JSON 格式
academic_info = AcademicInfo.objects.filter(user=user).first()
if academic_info:
response_data = {
"last_semester_score": str(academic_info.last_semester_score),
"this_semester_score": str(academic_info.this_semester_score),
"class_ranking": academic_info.class_ranking,
"strong_subject": academic_info.strong_subject,
"weak_subject": academic_info.weak_subject
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No academic info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户的学习情况信息
try:
data = json.loads(request.body)
last_semester_score = data.get("last_semester_score")
this_semester_score = data.get("this_semester_score")
class_ranking = data.get("class_ranking")
strong_subject = data.get("strong_subject")
weak_subject = data.get("weak_subject")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 AcademicInfo
academic_info, created = AcademicInfo.objects.get_or_create(user=user)
academic_info.last_semester_score = last_semester_score
academic_info.this_semester_score = this_semester_score
academic_info.class_ranking = class_ranking
academic_info.strong_subject = strong_subject
academic_info.weak_subject = weak_subject
academic_info.save()
return JsonResponse({"message": "Academic info updated successfully"})
def api_health_info_test(req):
return render(req, 'api_health_info_test.html')
class MyProtectedApiHealthInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取健康信息并返回 JSON 格式
health_info = HealthInfo.objects.filter(user=user).first()
if health_info:
response_data = {
"height": str(health_info.height),
"weight": str(health_info.weight),
"blood_type": health_info.blood_type,
"medical_history": health_info.medical_history,
"disability_status": health_info.disability_status,
"disability_category": health_info.disability_category,
"disability_grade": health_info.disability_grade
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No health info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户的健康信息
try:
data = json.loads(request.body)
height = data.get("height")
weight = data.get("weight")
blood_type = data.get("blood_type")
medical_history = data.get("medical_history")
disability_status = data.get("disability_status")
disability_category = data.get("disability_category")
disability_grade = data.get("disability_grade")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 HealthInfo
health_info, created = HealthInfo.objects.get_or_create(user=user)
health_info.height = height
health_info.weight = weight
health_info.blood_type = blood_type
health_info.medical_history = medical_history
health_info.disability_status = disability_status
health_info.disability_category = disability_category
health_info.disability_grade = disability_grade
health_info.save()
return JsonResponse({"message": "Health info updated successfully"})
def api_self_evaluation_test(req):
return render(req, 'api_self_evaluation_test.html')
class MyProtectedApiSelfEvaluationInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取自我评价信息并返回 JSON 格式
self_evaluation = SelfEvaluation.objects.filter(user=user).first()
if self_evaluation:
response_data = {
"strengths": self_evaluation.strengths,
"weaknesses": self_evaluation.weaknesses,
"study_attitude": self_evaluation.study_attitude,
"future_plans": self_evaluation.future_plans
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No self evaluation found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,更新用户的自我评价信息
try:
data = json.loads(request.body)
strengths = data.get("strengths")
weaknesses = data.get("weaknesses")
study_attitude = data.get("study_attitude")
future_plans = data.get("future_plans")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 查找或创建 SelfEvaluation
self_evaluation, created = SelfEvaluation.objects.get_or_create(user=user)
self_evaluation.strengths = strengths
self_evaluation.weaknesses = weaknesses
self_evaluation.study_attitude = study_attitude
self_evaluation.future_plans = future_plans
self_evaluation.save()
return JsonResponse({"message": "Self evaluation updated successfully"})
# =================== 以下字段是 一对多 ===================
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def api_hobbies_interests_test(req):
return render(req, 'api_hobbies_interests_test.html')
class MyProtectedApiHobbiesInterests(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取该用户的所有兴趣爱好信息
hobbies_interests = HobbiesInterests.objects.filter(user=user)
if hobbies_interests.exists():
response_data = []
for entry in hobbies_interests:
response_data.append({
"interests": entry.interests,
"extracurricular_activities": entry.extracurricular_activities
})
return JsonResponse(response_data, safe=False)
else:
return JsonResponse({"error": "No hobbies and interests found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,创建新的兴趣爱好记录
try:
data = json.loads(request.body)
interests = data.get("interests")
extracurricular_activities = data.get("extracurricular_activities")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 创建新的 HobbiesInterests 记录
new_entry = HobbiesInterests.objects.create(
user=user,
interests=interests,
extracurricular_activities=extracurricular_activities
)
return JsonResponse({"message": "Hobbies and interests added successfully"})
def api_social_practice_test(req):
return render(req, 'api_social_practice_test.html')
class MyProtectedSocialPractice(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取该用户的所有社会实践记录
social_practices = SocialPractice.objects.filter(user=user)
if social_practices.exists():
response_data = []
for entry in social_practices:
response_data.append({
"activity_name": entry.activity_name,
"activity_date": entry.activity_date,
"activity_location": entry.activity_location,
"activity_description": entry.activity_description,
"activity_outcome": entry.activity_outcome
})
return JsonResponse(response_data, safe=False)
else:
return JsonResponse({"error": "No social practice records found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,创建新的社会实践记录
try:
data = json.loads(request.body)
activity_name = data.get("activity_name")
activity_date = data.get("activity_date")
activity_location = data.get("activity_location")
activity_description = data.get("activity_description")
activity_outcome = data.get("activity_outcome")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 创建新的 SocialPractice 记录
new_entry = SocialPractice.objects.create(
user=user,
activity_name=activity_name,
activity_date=activity_date,
activity_location=activity_location,
activity_description=activity_description,
activity_outcome=activity_outcome
)
return JsonResponse({"message": "Social practice record added successfully"})
def api_family_info_test(req):
return render(req, 'api_family_info_test.html')
class MyProtectedFamilyInfo(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取该用户的家庭情况记录
family_info = FamilyInfo.objects.filter(user=user).first()
if family_info:
response_data = {
"family_member": family_info.family_member,
"economic_status": family_info.economic_status
}
return JsonResponse(response_data)
else:
return JsonResponse({"error": "No family info found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,创建或更新家庭情况记录
try:
data = json.loads(request.body)
family_member = data.get("family_member")
economic_status = data.get("economic_status")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 创建或更新 FamilyInfo 记录
family_info, created = FamilyInfo.objects.get_or_create(user=user)
family_info.family_member = family_member
family_info.economic_status = economic_status
family_info.save()
return JsonResponse({"message": "Family info updated successfully"})
def api_awards_punishments_test(req):
return render(req, 'api_awards_punishments_test.html')
class MyProtectedAwardsPunishments(APIView):
authentication_classes = [CustomTokenAuthentication] # 使用自定义的 Token 认证
permission_classes = [IsAuthenticated] # 需要用户认证才能访问
def get(self, request):
user = request.user
# 获取该用户的奖惩情况记录
awards_punishments = AwardsPunishments.objects.filter(user=user)
if awards_punishments.exists():
response_data = [
{
"award_name": ap.award_name,
"award_date": ap.award_date,
"award_organization": ap.award_organization,
"discipline_date": ap.discipline_date,
"discipline_issue": ap.discipline_issue,
"discipline_outcome": ap.discipline_outcome
} for ap in awards_punishments
]
return JsonResponse(response_data, safe=False)
else:
return JsonResponse({"error": "No awards or punishments found"}, status=404)
def post(self, request):
user = request.user
# 处理 POST 请求,创建或更新奖惩情况记录
try:
data = json.loads(request.body)
award_name = data.get("award_name")
award_date = data.get("award_date")
award_organization = data.get("award_organization")
discipline_date = data.get("discipline_date")
discipline_issue = data.get("discipline_issue")
discipline_outcome = data.get("discipline_outcome")
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format"}, status=400)
# 创建或更新 AwardsPunishments 记录
awards_punishment = AwardsPunishments.objects.create(
user=user,
award_name=award_name,
award_date=award_date,
award_organization=award_organization,
discipline_date=discipline_date,
discipline_issue=discipline_issue,
discipline_outcome=discipline_outcome
)
return JsonResponse({"message": "Awards and punishments info updated successfully"})

8
educheck/__init__.py Normal file
View File

@ -0,0 +1,8 @@
from __future__ import absolute_import, unicode_literals
# 在 Django 启动时加载 Celery
from .celery import app as celery_app
__all__ = ('celery_app',)

16
educheck/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for educheck 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/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educheck.settings')
application = get_asgi_application()

19
educheck/celery.py Normal file
View File

@ -0,0 +1,19 @@
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# 设置 Django 的 settings 模块
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educheck.settings')
# 创建 Celery 应用
app = Celery('educheck')
# 使用 Django 配置中的 Celery 配置
app.config_from_object('django.conf:settings', namespace='CELERY')
# celery.py
app.conf.broker_connection_retry_on_startup = True
# 自动发现所有的 tasks.py 文件
app.autodiscover_tasks()

184
educheck/settings.py Normal file
View File

@ -0,0 +1,184 @@
"""
Django settings for educheck project.
Generated by 'django-admin startproject' using Django 4.2.19.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
# __init__.py
import pymysql
pymysql.install_as_MySQLdb()
# 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/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-x!)cojyro)mcft%4r^8&wsn9f8o!5px1=@6mx4eu73ydczx&)j'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*', 'a.debin.cc']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'ec_user',
'authentication',
'diagnose'
]
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 = 'educheck.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'educheck.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 使用 MySQL 数据库
'NAME': 'educheck', # 数据库名称
'USER': 'root', # 数据库用户名
'PASSWORD': 'pacpac123.', # 数据库密码
'HOST': '127.0.0.1', # 数据库主机(如果数据库在本地就用 localhost
'PORT': '3306', # MySQL 默认端口是 3306
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/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/4.2/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'ec_user.EcUser'
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', # 只返回 JSON 格式的响应
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'authentication.authentication.CustomTokenAuthentication',
],
}
ERROR_CODE_MAP = {
# 1000 - 用户相关错误
# 2000 - 生成试卷相关错误
'2001': 'user not authorized to generate paper for this subject',
'2002': 'user has no remaining usage count for this subject',
'2003': 'user has no school info',
# 试卷查看
'2004': 'record file not found',
# 试卷下载
'2005': 'requested file not found'
}
OPAI_API_KEY = 'e119bd6c-a22a-404e-a002-6d72a2cea65d'
OPAI_BASE_URL = 'https://ark.cn-beijing.volces.com/api/v3'
WKHTMLTOPDF_PATH = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'
# settings.py
# celery -A educheck worker -l info -P eventlet
# celery -A educheck beat -l info
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' # 使用 Redis 作为消息中间件
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0' # Redis 存储任务结果
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'

34
educheck/urls.py Normal file
View File

@ -0,0 +1,34 @@
"""
URL configuration for educheck project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/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
from django.urls import include
from .views import user_profile
from .views import health_check
from .views import error_code_map
urlpatterns = [
path('admin/', admin.site.urls),
path('ec_user/', include('ec_user.urls')),
path('diagnose/', include('diagnose.urls')),
path('health/', health_check, name='health_check'),
path('error_code_map/', error_code_map, name='error_code_map'),
path('user_profile/<int:user_id>/', user_profile, name='user_profile'),
path('auth/', include('authentication.urls')),
]

15
educheck/views.py Normal file
View File

@ -0,0 +1,15 @@
# views.py
from django.shortcuts import render, get_object_or_404
from ec_user.models import EcUser
from django.http import JsonResponse
from django.conf import settings
def health_check(request):
return JsonResponse({"status": "ok", "version": "0.0.1"})
def error_code_map(request):
return JsonResponse(settings.ERROR_CODE_MAP)
def user_profile(request, user_id):
user = get_object_or_404(EcUser, id=user_id)
return render(request, 'user_profile.html', {'user': user})

16
educheck/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for educheck 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/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educheck.settings')
application = get_wsgi_application()

28
manage.py Normal file
View File

@ -0,0 +1,28 @@
#!/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', 'educheck.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()
# from django.contrib.auth.hashers import make_password
# celery -A educheck worker -l info -P eventlet
# celery -A educheck beat -l info

18
test_api.py Normal file
View File

@ -0,0 +1,18 @@
import requests
# 设置请求头
headers = {
'token': 'Token 486ef8198bb10ba6878eba95771c064ff64db81a' # 替换 your_token_here 为实际的 token
}
# 发送 GET 请求
url = 'http://a.debin.cc:55800/auth/' # 目标 URL
response = requests.get(url, headers=headers)
# 输出响应
if response.status_code == 200:
print("Response JSON:", response.json()) # 输出响应的 JSON 数据
else:
print(f"Request failed with status code {response.status_code}")