【问题标题】:How to save form data in flask with Vue.js如何使用 Vue.js 在 Flask 中保存表单数据
【发布时间】:2022-11-25 01:50:57
【问题描述】:

我正在做一个简单的任务,我必须使用我不太熟悉的工具。我需要以某种方式将 form数据保存到文本file,这是最好的选择)或至少将serialize保存到JSON,以便稍后将其转储到屏幕上。 有人可以至少指出我在哪里看的方向。我可以解决的某种起点。到目前为止我有这段代码,但它不会在任何地方保存数据

HTML

<form class="add-new" @submit="add" >

  <label >Nickname</label><br>

  <input type="text" v-model="nickname" ref="new"  autofocus name="nick" required><br>
  <span class="error" v-if="!nickname.match(/^[A-Za-z0-9]+$/) || nickname.length <= 2 || nickname.length >= 8">  {{message}}</span>

  <br></br>

  <label for="lname" required>Can you swim</label><br>
  <input type="radio" value="Yes" v-model="can_Swim" id="lname" name="je_plavec" required><br><br>

  <label >Your partner</label><br>

  <input type="text" v-model="partner" ref="new"  autofocus name="partner" >
  <br>
  <span class="error" v-if="!partner.match(/^[A-Za-z0-9]+$/) || partner.length <= 2 || partner.length >= 20"> {{message}}</span>
  <br><br>

  <section>
    <input  type="submit" value="submit">
    <a href="/index.html">

      <span>Back</span>

    </a>
  </section>

</form>
<transition-group name="student"
tag="ul" >
  <li class="student" v-for="(student, index) in students" :key="index">

    <article :class="{faded: student.nickname.length > 1}" >
     {{student.nickname}}
      <br>
      <span>

        {{student.partner}}
      </span>
      <br>

       <span>

        {{student.can_Swim}}
      </span>
      <br>


    </article>
  </li>
</transition-group>

Vue.js 代码:

<script>

  const vueApp  =  new Vue({
  el: '#app',
  data: {
    nickname:'',
    can_Swim:'',
    partner:'',
    message:"error",
    students:[]

  },

  methods:{
    add(e){
      e.preventDefault()
      this.students.push({
                    nickname:this.nickname,
                    can_Swim:this.can_Swim,
                    partner:this.partner
                }
                )
                this.nickname = ''
                this.partner = ''
                this.can_Swim = false,

                this.$refs.new.focus()
    },

  },


})

</script>


Python

@app.route("/registrace", methods=['GET'])
def reg_form():

    return render_template('registration.html')


我想像那样保存数据http://jsfiddle.net/exftm3b8/1/

【问题讨论】:

    标签: html json forms vue.js flask


    【解决方案1】:

    我的示例使用数据库来存储条目。
    为了实现这一点,使用了Flask SQLAlchemyFlask-MarshmallowMarshmallow-SQLAlchemyWebargs
    这些是使用此命令安装的。

    pip install flask-sqlalchemy flask-marshmallow marshmallow-sqlalchemy webargs
    

    完成所有条目并按下“添加”按钮后,它们将通过 AJAX 以 JSON 格式发送到服务器。这里所有的数据都会自动反序列化、再次验证并添加到数据库中。然后将数据库条目转换回 JSON 并发送回客户端,然后将其添加到学生列表中。

    如果重新加载页面,所有条目都从数据库中加载,序列化并发送到客户端。

    烧瓶 (./app.py)
    from flask import Flask, jsonify
    from flask_marshmallow import Marshmallow
    from flask_sqlalchemy import SQLAlchemy
    from webargs import fields, validate, ValidationError
    from webargs.flaskparser import use_args
    
    app = Flask(__name__)
    # Database configuration
    app.config.from_mapping(
        SQLALCHEMY_DATABASE_URI='sqlite:///demo.db'
    )
    db = SQLAlchemy(app)
    ma = Marshmallow(app)
    
    # Database model with all required columns
    class Student(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String, nullable=False, unique=True)
        partner = db.Column(db.String, nullable=False)
        can_swim = db.Column(db.Boolean, nullable=False, default=False)
    
    # Validation of the uniqueness of the name.
    def validate_uniqueness(val):
        # If a student with that name already exists, throw an error.
        if Student.query.filter_by(name=val).first():
            raise ValidationError('Name already exists.')
    
    # Scheme for serialization and validation
    class StudentSchema(ma.SQLAlchemyAutoSchema):
        name = ma.String(required=True, 
            validate=[
                validate.Length(min=2, max=8), 
                validate.Regexp(r'^[A-Za-z]+[0-9]*$'), 
                validate_uniqueness
            ]
        )
        partner = ma.String(required=True, 
            validate=[
                validate.Length(min=2, max=8), 
                validate.Regexp(r'^[A-Za-z]+[0-9]*$')
            ]
        )
        can_swim = ma.Boolean(required=True)
    
        class Meta:
            model = Student
            load_instance = True
    
    # Creation of the database. 
    # This can also be done via the flask shell.
    with app.app_context():
        db.drop_all()
        db.create_all()
    
    # Deliver the VueJS application as a static page.
    @app.route('/')
    def index():
        return app.send_static_file('index.html')
    
    # Creation of a new database entry
    @app.post('/students/new')
    @use_args(StudentSchema(), location='json')
    def students_create(student):
        # Save the data to the database.
        db.session.add(student)
        db.session.commit()
        # Convert the data to JSON.
        student_schema = StudentSchema()
        student_data = student_schema.dump(student)
        return jsonify(student_data)
    
    # Query and delivery of all existing database entries.
    @app.route('/students')
    def students():
        # Query all students from the database.
        students = Student.query.all()
        # Convert the data to JSON.
        student_schema = StudentSchema(many=True)
        student_data = student_schema.dump(students)
        return jsonify(student_data)
    
    # Error handler for failed validation.
    @app.errorhandler(422)
    @app.errorhandler(400)
    def handle_error(err):
        headers = err.data.get("headers", None)
        messages = err.data.get("messages", ["Invalid request."])
        if headers:
            return jsonify({"errors": messages}), err.code, headers
        else:
            return jsonify({"errors": messages}), err.code
    

    为了使 VueJS 的语法不与 Jinja2 的语法冲突,我将应用程序作为静态文件夹中的静态页面交付,绕过模板引擎。

    HTML (./static/index.html)
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Index</title>
    </head>
    <body>
    
        <div id="app">
            <form @submit.prevent="onSubmit">
                <div>
                    <label for="name">Name</label>
                    <input ref="name" v-model="student.name" id="name" autofocus />
                    <span v-if="student.name && !isValidName">Name invalid</span>
                </div>
                <div>
                    <label for="partner">Partner</label>
                    <input ref="partner" v-model="student.partner" id="partner" />
                    <span v-if="student.partner && !isValidPartner">Partner invalid</span>
                </div>
                <div>
                    <input type="checkbox" v-model="student.can_swim" id="can_swim" />
                    <label for="can_swim">Can Swim</label>
                </div>
                <button type="submit" :disabled="!isValid">Add</button>
            </form>
    
            <div>
                <ul>
                    <li class="student" v-for="(student, index) in students" :key="index">
                        <div>
                            {{ student.name }} & 
                            {{ student.partner }}, 
                            {{ student.can_swim ? "Can Swim" : "Can't swim" }}
                        </div>
                    </li>               
                </ul>
            </div>
        </div>
    
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script>
            const app = new Vue({
                el: '#app', 
                data: {
                    student: {
                        name: '', 
                        can_swim: false, 
                        partner: ''
                    }, 
                    students: [], 
                }, 
                methods: {
                    onSubmit() {
                        if(!this.isValid) return;
    
                        const url = '/students/new';
                        fetch(url, {
                            method: 'POST', 
                            headers: {
                                'Content-Type': 'application/json'
                            }, 
                            body: JSON.stringify(this.student)
                        }).then(resp => resp.ok && resp.json())
                            .then(data => {
                                if (data) {
                                    this.students.push(data);
                                    this.student = {
                                        name: '', 
                                        can_swim: false, 
                                        partner: ''
                                    };
                                    this.$refs.name.focus();
                                } else {
                                    this.$refs.name.select();
                                }
                            });
                    }, 
                    loadStudents() {
                        const url = '/students'; 
                        return fetch(url)
                            .then(resp => resp.ok && resp.json())
                            .then(data => { return data || []});
                    }
                }, 
                computed: {
                    isValidName() {
                        return this.student.name 
                                && 2 <= this.student.name.length
                                && this.student.name.length <= 8
                                && this.student.name.match(/^[A-Za-z]+[0-9]*$/);
                    }, 
                    isValidPartner() {
                        return this.student.partner 
                                && 2 <= this.student.partner.length
                                && this.student.partner.length <= 8
                                && this.student.partner.match(/^[A-Za-z]+[0-9]*$/);
                    }, 
                    isValid() {
                        return this.isValidName && this.isValidPartner;
                    }
                }, 
                async created() {
                    this.students = await this.loadStudents();
                }
            });
        </script>
    
    </body>
    </html>
    

    我已尝试通过代码中的 cmets 来指导您完成此操作,希望您继续使用它。

    【讨论】:

    • 感谢您的时间。它看起来非常专业,也很棒!
    猜你喜欢
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2015-07-14
    • 1970-01-01
    • 2021-03-12
    • 2015-12-03
    • 2022-10-23
    相关资源
    最近更新 更多