前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >list、dict和set的综合应用:排课系统(2)

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

作者头像
不可言诉的深渊
发布2020-06-16 14:50:59
6620
发布2020-06-16 14:50:59
举报

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

概述

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

登录

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

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

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

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

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

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

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

代码语言:javascript
复制
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())  # 输出登录之后的页面内容,会自动重定向,不需要多此一举访问登录后的页面

运行结果如图所示。

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

增加数据

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

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

增加教室

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

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

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

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

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

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

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

代码语言:javascript
复制
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,如图所示。

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

增加学生

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

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

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

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

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

增加课程

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

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

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

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

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

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

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

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

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

整合起来

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

代码语言:javascript
复制
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 的综合应用!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python机器学习算法说书人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档