首页 > 其他分享 >list、dict和set的综合应用:排课系统(2)

list、dict和set的综合应用:排课系统(2)

时间:2022-12-01 11:06:51浏览次数:42  
标签:set http admin 排课 list 127.0 0.1 session csrfmiddlewaretoken



差一点


我们就擦肩而过了

有趣

有用

有态度



list、dict和set的综合应用:排课系统(2)_登录页面


上回说到,我们主要实现了排课系统的后台数据的定义以及每个数据对象之间的关系,这一次我们就来批量增加一些数据,为了给后面的排课算法进行测试。



list、dict和set的综合应用:排课系统(2)_重定向_02







概述



因为 Django 是一个 Web 框架,数据的存储主要位于服务器,要想增加数据我们必须定义一个客户端,使用客户端来增加各种数据,在这里我不去直接操作数据库,而是访问管理员的后台页面进行增加数据,毕竟要用到 Django 的信号机制。因此,批量增加数据主要分为以下几步:登录、增加数据。



登录



首先来看一下登录部分的实现,首先我们必须启动 Django 项目,然后我们打开浏览器地址栏输入 http://127.0.0.1:8000/admin,会跳到登录页面,按 F12 打开浏览器开发者工具,如图所示。

list、dict和set的综合应用:排课系统(2)_数据_03

接下来我们尝试登录,看一下有哪些新的请求,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_04

我们发现第一个新的请求状态码是 302,估计是登陆后重定向到登录页面,我们点开查看详细信息,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_05

POST 请求,应该错不了了,我们来看看 POST 的数据有哪些,如图所示。

list、dict和set的综合应用:排课系统(2)_重定向_06

我们发现有一个 csrfmiddlewaretoken,这个 token 到底在哪里,一定是在登录之前就已经生成了,所以我们退出登录,回到登录页面,看看该页面是不是有 csrfmiddlewaretoken ,如图所示。

list、dict和set的综合应用:排课系统(2)_数据_07

果然有一个,接下来我们就是进行登录并查看 POST 数据的 csrfmiddlewaretoken 和这里的 csrfmiddlewaretoken 是不是一样的,如图所示。


list、dict和set的综合应用:排课系统(2)_数据_08

对比一下会发现果然是一样的,知道这些登录操作的代码实现就是轻而易举,代码如下:

from re import compile
from requests import Session
# csrfmiddlewaretoken 的正则表达式
csrfmiddlewaretoken_pattern = compile(r'<input type="hidden" name="csrfmiddlewaretoken" value="(.*?)">')
with Session()as session: # 启动一个会话,程序结束自动关闭
response = session.get('http://127.0.0.1:8000/admin/login/?next=/admin/') # 访问登录页面
csrfmiddlewaretoken = csrfmiddlewaretoken_pattern.findall(response.content.decode())[0] # 获取 csrfmiddlewaretoken
# 登录
response = session.post('http://127.0.0.1:8000/admin/login/?next=/admin/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken, 'username': 'mechrevo', 'password': '123456', 'next': '/admin/'})
print(response.content.decode()) # 输出登录之后的页面内容,会自动重定向,不需要多此一举访问登录后的页面

运行结果如图所示。

list、dict和set的综合应用:排课系统(2)_数据_09

既然有 logout,那么就登录成功。



增加数据



接下来我们看一下增加数据,在实现之前我们先想一下增加哪些数据,主要的增加的数据就是昨天定义的那些实体模型对应的数据,有教室、课程、班级、学生、教师,至于先增加什么数据,后增加什么数据不是随意的,当然也不是只有一种顺序,只要满足下面所描述的约束条件:

班级必须在学生的前面(没有班级,学生的对应班级也就无法选择),班级和教师必须在课程的前面(没有班级,课程对应的班级也就无法选择;没有教师,课程对应的授课教师同样也是无法选择)。


增加教室

list、dict和set的综合应用:排课系统(2)_登录页面_10


我们首先来看一下增加教室。先进入增加教室页面,打开浏览器开发者工具,如图所示。

list、dict和set的综合应用:排课系统(2)_重定向_11

接下来我们增加一个教室看看有没有新的请求,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_12

我们又发现了一个重定向,点进去查看详细信息,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_13

发现是一个 POST 请求,我们接下来就是看一下 POST 请求发送了什么数据,如图所示。

list、dict和set的综合应用:排课系统(2)_数据_14

果然又有一个 csrfmiddlewaretoken,这个东西对应的一串很长的字符串值就位于增加教室页面,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_15

接下来就是去验证页面中的值和 POST 发送的数据对应的值是不是一样,在这里我就不再截图放上来了,直接给出结论,是一样的值。

可以发现和登录时候的除了值其他都一样,所以获取其值的正则表达式也是一模一样。代码实现我们只需要在登录操作之后添加增加教室的操作,对应代码如下:

from re import compile
from requests import Session
# csrfmiddlewaretoken 的正则表达式
csrfmiddlewaretoken_pattern = compile(r'<input type="hidden" name="csrfmiddlewaretoken" value="(.*?)">')
with Session()as session: # 启动一个会话,程序结束自动关闭
response = session.get('http://127.0.0.1:8000/admin/login/?next=/admin/') # 访问登录页面
csrfmiddlewaretoken = csrfmiddlewaretoken_pattern.findall(response.content.decode())[0] # 获取 csrfmiddlewaretoken
# 登录
response = session.post('http://127.0.0.1:8000/admin/login/?next=/admin/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken, 'username': 'mechrevo', 'password': '123456', 'next': '/admin/'})
print(response.content.decode()) # 输出登录之后的页面内容,会自动重定向,不需要多此一举访问登录后的页面
response = session.get('http://127.0.0.1:8000/admin/course_scheduling_system/classroom/add/') # 访问增加教室页面
csrfmiddlewaretoken = csrfmiddlewaretoken_pattern.findall(response.content.decode())[0] # 获取 csrfmiddlewaretoken
# 增加教室
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/classroom/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken, 'name': '教室3', 'seat_number': '25',
'_addanother': 'Save and add another'})

运行完成之后我们看一下数据库里面有没有教室3,如图所示。

list、dict和set的综合应用:排课系统(2)_数据_16

果然可以,说明增加教室的操作成功了。接下来重点看一下增加学生和课程,因为增加教室、班级、教师都很简单,我演示了一个增加教室,增加班级和增加教师都是类似的逻辑,那么为什么增加学生和课程不是和增加教室类似的逻辑呢?至于这个问题,继续往下看就知道了。


增加学生

list、dict和set的综合应用:排课系统(2)_登录页面_10


接下来我们直接跳到增加学生的操作。增加班级在此之前大家自己完成,我上面也说明了,和增加教室差不多的逻辑。

我们进入增加学生页面,打开浏览器开发者工具,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_18

我们尝试增加一个学生,看看有没有新的请求,如图所示。

list、dict和set的综合应用:排课系统(2)_登录页面_19

又有一个重定向,点进入查看详细信息发现还是一个 POST 请求,请求的数据如图所示。

list、dict和set的综合应用:排课系统(2)_数据_20

注意 grade 对应的 1 表示班级的 id!增加学生就这一个地方需要注意,代码实现大家尝试自己完成,我就不给出代码了。


增加课程

list、dict和set的综合应用:排课系统(2)_登录页面_10


最后我们来看一下增加课程的操作。增加教师在此之前大家自己完成,我上面也说明了,和增加教室的信息差不多的逻辑。

我们来到增加课程页面,打开浏览器开发者工具,如图所示。

list、dict和set的综合应用:排课系统(2)_重定向_22

接着和之前一样,增加一个课程,看看有没有新的请求,如图所示。

list、dict和set的综合应用:排课系统(2)_数据_23

又有一个重定向,点进入查看信息发现是 POST 请求,看一下 POST 的数据,如图所示。

list、dict和set的综合应用:排课系统(2)_重定向_24

哈?!居然有同名参数?!那么这个时候会话的 post 方法的 data 参数对应的字典要怎么写?字典的键不可以重复,这里有两种解决方案:(1)元组列表,格式如下:

data=[..., ('grades', '1'), ('grades', '2')]

(2)把重复的键对应的值用列表包起来,格式如下:

data={..., 'grades': ['1', '2']}

这里 grades 对应的多个值是班级的 id,teachers 对应的多个值是教师的 id,知道这些,代码实现就是轻而易举,大家自己尝试完成。



整合起来



既然增加一条数据弄懂了,批量增加数据就非常简单:使用 for 循环即可。接下来就是依照之前的约束条件,选择一个合理的顺序,把代码整合起来就行了,最后直接给出完整源代码。

from random import choice, randint, sample, shuffle
from re import compile
from requests import Session
csrfmiddlewaretoken_pattern = compile(r'<input type="hidden" name="csrfmiddlewaretoken" value="(.*?)">')
with Session()as session:
session.post('http://127.0.0.1:8000/admin/login/?next=/admin/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/login/?next=/admin/').content.decode())[0],
'username': 'mechrevo', 'password': '123456', 'next': '/admin/'})
# 教室
for i in range(1, 21):
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/classroom/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/course_scheduling_system/classroom/add/').content.decode())[0],
'name': f'教室{i}', 'seat_number': str(choice((20, 24, 25, 28, 30))), '_addanother': 'Save and add another'})
# 班级
for i in range(1, 11):
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/grade/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/course_scheduling_system/grade/add/').content.decode())[0],
'name': f'班级{i}', '_addanother': 'Save and add another'})
# 学生
li = [25]*10
for i in range(0, 10, 2):
offset = randint(0, 5)
li[i] -= offset
li[i+1] += offset
shuffle(li)
student_id = 1
for i in range(1, 11):
for _ in range(li[i-1]):
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/student/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/course_scheduling_system/student/add/').content.decode())[0],
'name': f'学生{student_id}', 'grade': str(i), '_addanother': 'Save and add another'})
student_id += 1
# 教师
for i in range(1, 21):
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/teacher/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/course_scheduling_system/teacher/add/').content.decode()),
'name': f'教师{i}', '_addanother': 'Save and add another'})
# 课程
for i in range(1, 11):
session.post('http://127.0.0.1:8000/admin/course_scheduling_system/course/add/', {
'csrfmiddlewaretoken': csrfmiddlewaretoken_pattern.findall(session.get(
'http://127.0.0.1:8000/admin/course_scheduling_system/course/add/').content.decode())[0],
'name': f'课程{i}', 'number_per_week': str(randint(1, 3)), 'grades': [str(e)for e in sample(range(
1, 11), randint(1, 3))], 'teachers': [str(e)for e in sample(range(1, 21), randint(2, 6))],
'_addanother': 'Save and add another'})

我在这里增加了 20 个教室,每个教室座位数在(20, 24, 25, 28, 30)之间进行选择;10 个班级;250 个学生,一个班级至少有 20 个学生,至多有 30 个学生,平均一个班级 25 个学生;20 个教师;10 门课程,每门课程一周 1~3 节,属于 1~3 个班级的课程,有 2~6 个授课教师。

今天的内容就到这里,下回我们编写排课算法——真真正正的 list、dict 和 set 的综合应用!

今天的文章有不懂的可以后台回复“加群”,备注:小陈学Python,不备注可是会被拒绝的哦~!



list、dict和set的综合应用:排课系统(2)_登录页面_25




标签:set,http,admin,排课,list,127.0,0.1,session,csrfmiddlewaretoken
From: https://blog.51cto.com/u_15829940/5901365

相关文章