zoukankan      html  css  js  c++  java
  • vue+python前后端MVC的初探

    0.继续上次的思路,将持续探索mvc。python的优势是简洁明快,我并不想为了适应mvc模式,而让后端结构看起来极为臃肿。一直在寻找关于mvc的权威书籍。

    1.这次前端用添加了用户列表功能。点击下面列表,上面就会同步显示信息,
      1.1 vue双向绑定的优势,如果用传统jquery方式,实现这个功能能把人写吐血。
      1.2 还尝试了async await语法,这是新版js的特性,等待异步事件。其实会使用await也就理解了promise。
      1.3 也使用了vue 的v-if 语法。这也是个美味的语法,很方便。
      1.3 我一直认为,学习语言最好的方式,先不求甚解的通读一遍基本语法,然后构思一个项目,随着项目的迭代,语言能力也会随之提高。


    <template>
      <div class="app-container">
        <el-form ref="userForm" :model="userData" :rules="rules" status-icon label-width="100px" class="demo-ruleForm">
          <el-form-item label="用户ID" prop="id">
            <el-input ref="userid" v-model="userData.id" autocomplete="off" disabled></el-input>
          </el-form-item>
          <el-form-item label="用户名" prop="username">
            <el-input ref="username" v-model="userData.username" autocomplete="off"></el-input>
          </el-form-item>
          <el-row>
            <el-col :span="colWidth">
              <el-form-item label="密码" prop="password">
                  <el-input ref="password" v-model="userData.password" type="password" autocomplete="off"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="colWidth" v-if="showRePassword()">
              <el-form-item label-width=0 prop="rePassword" >
                  <el-input type="password" v-model="userData.rePassword" autocomplete="off"></el-input>
              </el-form-item>
            </el-col>
          </el-row>
          
          <el-form-item>
            <el-button @click="addUser()">新增</el-button>
            <el-button @click="saveUser()">保存</el-button>
          </el-form-item>
        </el-form>
        <el-table :data="tableData" @row-click="showDetails" style=" 100%">
          <el-table-column prop="id" label="编号" min-width="10%"></el-table-column>
          <el-table-column prop="username" label="用户名" min-width="30%"></el-table-column>
          <el-table-column prop="alternativeID" label="用户别名" v-show="true" min-width="50%"></el-table-column>
        </el-table>
      </div>
    </template>
    
    <script>
    import qs from 'qs'
    import service from '../utils/request'
    export default {
      data() {
        var checkUsername = async (rule, value, callback) => {
          if (value === '') {
            callback(new Error('用户名不可为空'))
          } else if (await this.existsUsername(value)){
            callback(new Error('用户名已占用'))
          } else {
            callback();
          }
        };
        var checkPassword = (rule, value, callback) => {
          if (value === '') {
            callback(new Error('请输入密码'));
          } else {
            if (this.userData.rePassword !== '') {
              this.$refs.userForm.validateField('rePassword');
            }
            callback();
          }
        };
        var checkRePassword = (rule, value, callback) => {
            if (value === '') {
              callback(new Error('请再次输入密码'));
            } else if (value !== this.userData.password) {
              callback(new Error('两次输入密码不一致!'));
            } else {
              callback();
            }
        };
        return {
          status:'',
          colWidth:24,
          userData:{
            id: '',
            username: '',
            password: '',
            rePassword:''
          },
          rules: {
            username: [
              { validator: checkUsername, trigger: 'blur' }
            ],
            password: [
              { validator: checkPassword, trigger: 'blur' }
            ],
            rePassword: [
              { validator: checkRePassword, trigger: 'blur' }
            ]
          },
          tableData: []
        };
      },
      mounted:function(){
        this.getUserList()
      },
      methods: {
        showRePassword() { 
          let canShow = false
          if ((this.status == 'modify') || (this.status == 'add')){
            canShow = true
          } else {
            canShow = false
          }
    
          return canShow
        },
        getUserList() {
          let _this = this
          service({url: '/userlist',method: 'get'})
            .then(response => {
              const { data } = response
              _this.tableData = data.data
              console.log(self.tableData)
            })
            .catch(error => {
              console.log(error)
            })
        },
        showDetails(row) {
          console.log('showDetail '+row)
          this.userData.id = row.id
          this.userData.username = row.username
          this.userData.password = row.password
        },
        saveUser() {     
          let _this = this
          this.$refs['userForm'].validate((valid) => {   
            if (valid) {
              service({url: '/saveuser',method: 'post',data: qs.stringify(this.userData)})
                .then(response => {
                  const { data } = response
                  alert('submit!!!' +'
    '+ data.msg)
                })
                .then(() => {
                    _this.getUserList()
                    _this.colWidth = 24
                    _this.status = ''
                })
                .catch(error => {
                  console.log(error)
                })
            } else {
              console.log('illegad submit!!');
              return false;
            }
          })
        },
        addUser() {
          this.colWidth = 12
          this.status = 'add'
          console.log('clearForm')
          this.$refs['userForm'].resetFields();
        },
        
        async existsUsername(value) {
          let exists = false
          await service({url: '/existsusername',method: 'get',params: {username: value} })
            .then(response => {
              const { data } = response
              exists = data.data.exists
            })
          return exists
        }
      }
    }
    </script>
    UserManage.vue

    2.后端代码,在controller层和service层分别添加了usermanage.py.
      2.1 比起login代码,我把从外部获取数据的方法全移动到controller层,我考虑,controller层是后端的唯一窗口,禁止其他层从外部获取数据。
      2.2 另外我一直在思考是不是把dao层拆出model层,把数据库实体独立看待。而dao层单纯负责增删改查工作。但这么做会不会导致解耦过度。这个问题先延后,看以后代码走向,目前我无法预判。
      2.3 还有一个思考,controller层能不能直接访问dao层呢?真是难以抉择。那么换一个问法,controller为什么要访问dao层?当然是前端业务需要,既然有业务需要,什么样的业务简单到没有业务逻辑,只有入库动作?哪怕是简单入库动作,也该做入库前的数据校验。从我目前对dao层的理解,此层应该远离业务逻辑,此层应该更倾向于数据库级。是不是可以这么理解,dao层就相当于数据库查询语言SQL。而model层就相当于数据库的表。如果我的理解是正确的,那么刚才的两个思考也该有答案了。 

    from flask import jsonify
    from dao.database import init_db,db_session
    from dao.operator import Operator
    import time
    
    def userList():
        users = db_session.query(Operator).filter(1==1).all()
        returnData = {'code': 0, 'msg': 'success', 'data': Operator.to_json(users)}
        return jsonify(returnData),200
    
    def existsUsername(username):
        # time.sleep(3)
        user = db_session.query(Operator).filter(Operator.username == username).first()
        if (user == None):
            return False
        else:
            return True
    
    def addUser(username,password): 
        if (not existsUsername(username)):
            oper = Operator(None,username, password)
            db_session.add(oper)
            db_session.commit()
            returnData = {'code': 0, 'msg': 'success', 'data': username+' success'}
            return jsonify(returnData),200
        else:
            returnData = {'code': 1, 'msg': 'failed', 'data': username+' faild'}
            return jsonify(returnData),200
    usermanage.py(service)
    from flask import Blueprint,jsonify,request
    import service.usermanage as usermanage
    
    bp = Blueprint('usermanage_page',__name__)
    
    @bp.route('/userlist')
    def userlist():
        return usermanage.userList()
    
    @bp.route('/existsusername')
    def existsUsername():
        username = request.args.get('username', '')
        exists = usermanage.existsUsername(username)
        returnData = {'code': 0, 'msg': 'success', 'data': {'exists':exists}}
        return jsonify(returnData),200
    
    @bp.route('/saveuser', methods=['POST'])
    def saveUser():
        username = request.form['username']
        password = request.form['password']
        returnData = usermanage.addUser(username,password)
        return returnData
    usermanage.py(controller)

    3.在写后端代码时,引发了另一个问题,就是关于函数错误码定义问题。http本身有完善的错误码,而我后端代码也该定义一些合适的错误码。

    4.有了用户,当然也该有角色分配。所以接下来会探索角色和用户的联系。sqlalchemy将是下面重点学习内容。当然前端可以刷路由概念了。

  • 相关阅读:
    MySQL高可用架构之MHA
    DateTimeFormatter
    mysql实现行拼接、列拼接
    图形数据库 Neo4j 开发实战
    除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制(解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();),信号槽不就是一个回调函数嘛
    moveToThread的根本目的还是为了处理QObject的事件循环(如果为空指针的话,当前对象的所有的事件都不处理了),看官方说明就知道了
    专访紫光刁石京:资本追逐下产业“过热” 人才培养需塌下心(企业这么多年好不容易积累起来的人才队伍,被别人这么一挖,一切付诸东流)
    为QML创建C++插件(下载)
    Qt Quick Controls 与 Qt Quick Controls 2的区别(详细对照)
    asp.net core zipkin
  • 原文地址:https://www.cnblogs.com/yaoshi641/p/13524749.html
Copyright © 2011-2022 走看看