美文网首页React.js前端xuexi
使用Sqlite3+Express.js+React实现在线答题

使用Sqlite3+Express.js+React实现在线答题

作者: fanzhh | 来源:发表于2018-01-28 19:46 被阅读137次

    将word格式的题库转为txt格式,导入至sqlite3中,使用Express.js做服务端提供json格式数据,使用React做前端获取服务端数据。本文为第一部分,实现导入数据和服务端提供数据API接口。

    数据导入

    源格式

    源题库为word格式,题型分别为单选、多选和判断题。

    单选题 多选题 判断题

    转为txt格式

    为便于读取,word格式另存为txt格式,文件名为questions.txt

    建立数据库

    我使用的IPython来建立数据库:

    import sqlite3
    conn=sqlite3.connect('mydb.db')
    c=conn.cursor()
    c.execute('''create table (
                     id int primary key, // 主键 
                     description text,  // 题目
                     answer text,  // 答案
                     A text, //选择项A。判断题时,A为正确。
                     B text, //选择项B。判断题时,B为错误。
                     C text, //选择项C
                     D text, //选择项D
                     E text, //选择项E。默认最多5个选择项。
                 )''')
    c.commit()
    

    从txt文件中提取试题信息

    txt题库中,每道题都以阿拉伯数字+.开始,形如1.,选择题题干中正确答案在全角括号中,形如(ABCD),判断题题干行中会有×符合,据此提取数据。代码如下:

    import re // 导入正则表达式模块
    p1=re.compile("\d+.")  // 判断是否为新的题干的正则表达式
    p2=re.compile("((.+))") // 提取正确答案的正则表达式
    f=open('questions.txt','r') // 打开文本文件
    lines=f.readlines()  // 读取全部文本
    questions = [] // 建立空题库,在遍历文本中追加
    description='' // 初始化题目
    answer='' // 初始化答案
    A='' // 初始化选项
    B=''
    C=''
    D=''
    E=''
    for line in lines:
        if p1.match(s): // 该行以数字+.开始,遇到一道新题
            if description != '': // 确定题目非空
                questions.append([description,answer,answerA,   // 新题追加到题库中,
                    answerB,answerC,answerD,answerE,remark])
            question=''  // 然后清空各字段
            answer=''
            answerA=''
            answerB=''
            answerC=''
            answerD=''
            answerE=''
            remark=''
            if '×' in s or '√' in line: // 这是一道判断题吗
                    description=s[:s.find('(')] // 提取题目表述
                    answerA='√'
                    answerB='×'
                    remark='2' // 为便于排序,备注中判断题标记为2
                    if '×' in s:  // 答案为×
                        answer='B'
                    elif '√' in s:
                        answer='A'
                    continue // 判断题没有选择项,所以直接跳到下一个循环
            else: // 不是判断,那就是选择题了
                      description=s[:s.find('(')+1]+s[s.find(')'):] // 提取题目描述
                      answer=p2.search(s).group(1).strip()
                      if len(answer)>1:
                           remark='1' // 多选题标记为1
                      else:
                           remark='0' // 单选题标记为0
        else: // 该行不是以数字+.开始,是选择项
            answers = s.split() // 选择项之间以空格分开
            for an in answers:
                if an.startswith('A'): // 选项A
                    answerA=an
                elif an.startswith('B'): // 选项B
                    answerB=an
                elif an.startswith('C'): // 选项C
                    answerC=an
                elif an.startswith('D'): // 选项D
                    answerD=an 
                elif an.startswith('E'): // 选项E
                          answerE=an
    

    试题信息导入数据库

    现在,所有题目都在questions数组中,可以插入到数据库中了:

    conn = sqlite3.connect('mydb.db') // 连接数据库
    c=conn.cursor()  // 获取游标
    i=1 // 计数器,做ID赋值用
    for q in questions:
        // 执行插入
        c.execute("insert into question(id,description,answer,A,B,C,D,E,remark) values(%d,'%s','%s','%s','%s','%s','%s','%s','%s')"%(i,q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7]))                                                 
        i=i+1
    conn.commit() // 提交
    

    使用express.js建立服务端

    新建目录express-sqlite3:

    $ mkdir express-sqlite3 ; cd express-sqlite3
    

    建立新文件package.json,输入以下内容:

    {
      "name": "express-sqlite3",
      "version": "1.0.0",
      "description": "",
      "main": "restapi.js",
      "dependencies": {
        "express": "^4.13.1",
        "sqlite3": "https://github.com/mapbox/node-sqlite3/tarball/master"
      },
      "devDependencies": {},
      "scripts": {
        "start": "node restapi.js"
      },
      "author": "",
      "license": "ISC"
    }
    

    执行npm install安装包。
    新建db目录,将上一步生成的mydb.db文件拷贝至此目录内。
    新建restapi.js文件,输入以下内容:

    var sqlite3 = require('sqlite3').verbose();
    var db = new sqlite3.Database('db/mydb.db');
    
    var express = require('express');
    var restapi = express();
    
    restapi.get('/data', function(req, res){
        results = [];
        db.all("SELECT * from question order by remark,description", function(err, rows){
            rows.map((row)=>{
            results.push({"id":row.id,
                      "description":row.description,
                      "answer":row.answer,
                      "A":row.A,
                      "B":row.B,
                      "C":row.C,
                      "D":row.D,
                      "E":row.E,
                      "remark":row.remark,})
            });
            res.json(results);
        });
    });
    
    restapi.listen(3000); // 在3000端口监听
    
    console.log("Submit GET to http://localhost:3000/data");
    

    在命令行执行:

    npm start
    > express-sqlite3@1.0.0 start /home/fanzhh/projects/express-sqlite3
    > node restapi.js
    Submit GET to http://localhost:3000/data
    

    此时在浏览器输入地址http://localhost:3000/data,页面显示如下:

    json数据

    OK。下一章我们将用React实现前端的在线答题。

    相关文章

      网友评论

        本文标题:使用Sqlite3+Express.js+React实现在线答题

        本文链接:https://www.haomeiwen.com/subject/fuczaxtx.html