Vue + Flask 小知识(四)

2019-07-30 15:10:06 浏览数 (1)

微信公众号:萝卜大杂烩 关注可了解更多的原创内容。问题或建议,请公众号留言或加本人微信; 如果你觉得文章对你有帮助,欢迎加微信交流

今天继续分享 Vue 系列,提交多对多表单

页面布局

首先有一个简单的表单,一个必填的输入框,一个 textarea 类型输入框,还有两个多选的下拉框 页面效果如下:

表结构

再来看看表结构是怎样的 这里主要用到了三张表:

  1. Project 表,存储项目信息
  2. Rel_Testsuit_Project 表,测试集和项目的关系表
  3. Rel_User_Project 表,用户和项目的关系表

另外其实还有 User 和 Testsuit 表,但是在本例子中并不涉及

Project 表:

代码语言:javascript复制
class Project(db.Model):
    __tablename__ = 'projects'
    id = db.Column(db.Integer, primary_key=True)
    create_time = db.Column(db.Date)
    projectname = db.Column(db.String(64), unique=True, index=True)
    description = db.Column(db.Text)

Rel_Testsuit_Project 表

代码语言:javascript复制
class Rel_Testsuit_Project(db.Model):
    __tablename__ = 'rel_testsuit_project'
    id = db.Column(db.Integer, primary_key=True)
    testsuit_id = db.Column(db.Integer)
    project_id = db.Column(db.Integer)

Rel_User_Project 表

代码语言:javascript复制
class Rel_User_Project(db.Model):
    __tablename__ = 'rel_user_project'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer)
    project_id = db.Column(db.Integer)

Vue 代码

再来看看页面布局的代码 在新创建的 .vue 文件中,添加布局代码

代码语言:javascript复制
<el-dialog title="新增项目" :visible.sync="dialogFormVisible">
        <el-form :model="form" ref="form">
            <el-form-item label="项目名称" :label-width="formLabelWidth" prop="projectname"
            :rules="[{required: true, message: '项目名称不能为空', trigger: 'change'}]">
                <el-input v-model="form.projectname" placeholder="输入项目名称">
                </el-input>
            </el-form-item>
            <el-form-item label="项目描述" :label-width="formLabelWidth">
                <el-input type="textarea" :autosize="{ minRows: 2, maxRows: 8}" v-model="form.description" auto-complete="off"></el-input>
            </el-form-item>
            <el-form-item label="测试集" :label-width="formLabelWidth"  prop="suitname">
                <el-select v-model="form.suitname" multiple placeholder="请选择测试集" v-on:focus="getSuit()">
                    <el-option
                    v-for="item in suits"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label">
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="人员" :label-width="formLabelWidth"  prop="username">
                <el-select v-model="form.username" multiple placeholder="请添加人员" v-on:focus="getUser()">
                    <el-option
                    v-for="item in userSelection"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label">
                    </el-option>
                </el-select>
            </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取 消</el-button>
            <el-button type="primary" :loading="loginLoading" @click="save('form'), resetForm('form')">确 定</el-button>
        </div>
    </el-dialog>

在对话框中定义了 :visible.sync="dialogFormVisible",当点击某个按钮,比如:添加,则设置 dialogFormVisible = true,那么该对话框就会展示在页面上了。 其中函数 getSuit 和 getUser 分别从后台回去数据,展示在下拉框中。

下面是脚本代码部分

代码语言:javascript复制
<script>
  import ToolBar from '~/components/ToolBar/ToolBar.vue';
  import HelpHint from '~/components/HelpHint/HelpHint.vue';
  import projectdata from '../../api/testproject.js';
  import suitdata from '../../api/testsuit.js';
  import dealdata from '../../api/data.js';
  export default {
    data() {
      return {
          formLabelWidth: '120px',
          loginLoading: false,
          dialogFormVisible: false,
          userSelection: [],
          form: {
            id: '',
            projectname: '',
            suitname: [],
            description: '',
            username: [],
          },
          projects: [],
          suits: [],
          users: [],
        searchParams:{
            projectName:'',
            postType:'',
            projectStatus:'published',
        },
      }
    },
    methods: {
      resetForm(formName){
            this.$refs[formName].resetFields();  
      },
      getProject(){
          let APP = this;
          let projectName = this.searchParams.projectName;
          let projectStatus = this.searchParams.projectStatus;
          let parm = {projectName: projectName, projectStatus:projectStatus};
          projectdata.getProject(APP, parm);
      },
      getSuit(){
          let APP = this;
          suitdata.getSuit(APP);
      },
      getUser(){
          let APP = this;
          dealdata.getuser()
          .then(res => {
              if(res.data.code == 200) {
                APP.userSelection = res.data.selection_data;
                //console.log(APP.projects);
                //console.log(APP.userSelection);
                }
          })
          .catch(function(error){
              APP.$message.error("网络错误");
          })
      },
      save(formName){
          let APP = this;
          this.$refs[formName].validate((valid) => {
            var projectname = this.form['projectname'];
            var description = this.form['description'];
            var suitname = this.form['suitname'];
            var username = this.form['username'];
            if(valid) {
                var data = {
                    projectname: projectname, description: description,
                    suitname: suitname, username: username
                };
                //console.log(data);
                APP.loginLoading = true;
                dealdata.saveproject(data)
                .then(res => {
                    if(res.data.code == 200){
                        APP.loginLoading = false;
                        APP.dialogFormVisible = false;
                        this.$message.success(res.data.message);
                    } else{
                        APP.loginLoading = false;
                        this.$message.error(res.data.message);
                    }
                    projectdata.getProject(APP);
                })
                .catch(function(error) {
                    APP.loginLoading = false;
                    console.log(APP.$message.error("网络错误"));
                })

                }else{
                    APP.loginLoading = false;
                    console.log("error save");
                    if(projectname == ''){
                        this.$message.error('项目名称不能为空');
                        return false;
                    };
                }
          })
      },
    },
    mounted(){
        this.getProject();
    },
    components: {
        ToolBar,HelpHint
    }
  }
</script>

这里我们只关心 save 函数,组装 data 数据,通过 post 方法提交到后台。同时我们也可以看到,初始阶段,dialogFormVisible 是设置为 false 的。

API 代码

下面我们来看看后台的 API,还是先给出完整的代码。

代码语言:javascript复制
class ProjectAddView(Resource):
    def post(self):
        try:
            projectinfo = request.get_json()
            print(projectinfo)
            if 'projectname' in projectinfo:
                projectname = request.get_json()['projectname']
            else:
                return {'code': 422, 'message': '请输入名称'}
            if 'description' in projectinfo:
                description = request.get_json()['description']
            else:
                description = ''
            if 'suitname' in projectinfo:
                suitname = request.get_json()['suitname']
            else:
                suitname = ''
            if 'username' in projectinfo:
                username = request.get_json()['username']
            else:
                username = ''
            ptname = Project.query.filter_by(projectname=projectname).first()
            if ptname:
                return {'code': 422, 'message': "该项目已经存在"}
            else:
                c_time = datetime.date.today()
                project = Project(projectname=projectname, description=description, create_time=c_time)
                db.session.add(project)
                db.session.commit()
                projectid = Project.query.filter_by(projectname=projectname).first().id
                if len(suitname) != 0:
                    for ts in suitname:
                        suitid = TestSuit.query.filter_by(testsuitname=ts).first().id
                        r_ts_pt = Rel_Testsuit_Project(testsuit_id=suitid, project_id=projectid)
                        db.session.add(r_ts_pt)
                        db.session.commit()
                if len(username) != 0:
                    for u in username:
                        userid = User.query.filter_by(username=u).first().id
                        r_us_pt = Rel_User_Project(user_id=userid, project_id=projectid)
                        db.session.add(r_us_pt)
                        db.session.commit()
                return {'code': 200, 'message': 'Project创建成功'}
        except:
            raise

最主要的部分,就是判断 suitname 和 username,因为这两个变量从前端传过来时都是列表形式的,所以只要判断下其长度是否为0,就能判断出提交表单时,是否选择了这两个选项,如果长度不为0,则循环这两个列表,并分别取出对应表中的 ID 值,保存至中间表中。

这样,就完成了多对多的绑定操作。


猜泥稀饭:

Vue Flask 实现单页面应用

Vue Flask 小知识(一)

Vue Flask 小知识(二)

Vue Flask 小知识(三)

0 人点赞