Flask与JavaScript

3 投票
2 回答
4491 浏览
提问于 2025-04-18 16:22

我正在用Flask开发一个网页服务器应用程序。到目前为止,我创建了一个小框架,用户可以在图片上用画布和JavaScript画一些框。我把这些框的信息和图片的信息都保存在JavaScript的一个数组里。不过,这些数据必须提交并存储到服务器端的数据库里。因此,我有一个按钮可以提交这些内容,但我不知道怎么获取我在JavaScript里保存的数据,也就是框和图片的信息。

这样获取JavaScript的信息并提交,是否可行呢?我想过一些办法,比如把信息打印在隐藏的HTML元素里,或者使用AJAX把信息发送到服务器,但我觉得这些方法可能不是在Flask中处理这个问题的“正确”方式。那么,有人有什么想法吗?以下是我认为可能与理解我的问题相关的部分代码:

Models.py:我这里的类有点不同:Blindmap=Image,Label=boxes。我的数据库是用SQLAlchemy建模的。

blindmap_label = db.Table('blindmap_label',
db.Column('blindmap_id', db.Integer, db.ForeignKey('blindmap.id', ondelete = 'cascade'), primary_key = True),
db.Column('label_id', db.Integer, db.ForeignKey('label.id', ondelete = 'cascade'), primary_key = True))


class Blindmap(db.Model):

   __tablename__ = 'blindmap'

   id = db.Column(db.Integer, primary_key = True)
   description = db.Column(db.String(50))
   image = db.Column(db.String)

   labels = db.relationship('Label', secondary = blindmap_label, backref = 'blindmaps', lazy = 'dynamic')

   def __init__(self, label = None, **kwargs):
       if label is None:
          label = []
       super(Blindmap, self).__init__(**kwargs)

   def add_label(self, label):
       if label not in self.labels:
          self.labels.append(label)
          db.session.commit()

   def __repr__(self):
       return '<Blindmap %r:>' % (self.id)


class Label(db.Model):
   __tablename__ = 'label'

   id = db.Column(db.Integer, primary_key = True)
   name = db.Column(db.String(50))
   x = db.Column(db.Integer)
   y = db.Column(db.Integer)
   w = db.Column(db.Integer)
   h = db.Column(db.Integer)

   def __repr__(self):
      return '<Pair %r:>' % (self.id)

我的控制器信息:

@app.route('/')
@app.route('/index')
def index():
   blindmaps = db.session.query(Blindmap).all()
   return render_template("index.html",
      title = 'Home',
      blindmaps = blindmaps)

@app.route('/new', methods = ['GET', 'POST'])
def new():
   form = BlindmapForm()
   if request.method=="POST":
     if form.validate_on_submit():
        blindmap = Blindmap(description=form.description.data)
        redirect(url_for('index'))
   return render_template("new.html",
   title = 'New Blindmap',
   form=form)

2 个回答

1

你需要做的是使用AJAX,这是一种技术,可以在网页加载到用户的浏览器后“异步”地发送请求并从服务器获取响应,使用的是JavaScript。AJAX实际上是“异步JavaScript和XML”的缩写(虽然它不一定完全是异步的,也不一定非得使用XML作为数据交换格式)。这是访问网络API的标准方式,比如你用Flask创建的API,通过URL(也就是路由)来获取和保存后端的对象。

现代浏览器都提供了一个叫做XMLHttpRequest的构造函数(MDN文档),可以用来创建对象,让网页在加载后与网络服务器进行通信。

为了提高不同浏览器之间的兼容性和代码的可维护性,你可以使用一些JavaScript框架,它们会把XMLHttpRequest封装成更简单的形式。我这些年来一直在有效地使用jQuery来实现这个目的。特别是,在你的情况下,你需要使用jQuery.ajax方法(或者对于POST操作,可以用它的简写jQuery.post)。

不过,我会给你一个小例子,展示如何使用原生JavaScript来执行这样的请求,这样即使在使用框架时,你也能理解浏览器里发生了什么:

// Create an instance of the XHR object
var postNewObject = new XMLHttpRequest();

// Define what the object is supposed to do once the server responds
postNewObject.onload = function () {
  alert('Object saved!');
};

// Define the method (post), endpoint (/new) and whether the request
// should be async (i.e. the script continues after the send method
// and the onload method will be fired when the response arrives)
postNewObject.open("post", "/new", true);

// Send! 
postNewObject.send(/* Here you should include the form data to post */);

// Since we set the request to be asynchronous, the script
// will continue to be executed and this alert will popup
// before the response arrives
alert('Saving...');

想了解更多关于使用XMLHttpRequest的信息,可以参考MDN。

3

试试用 jQuery 的 ajax:

function upload() {

    // Generate the image data
    var img= document.getElementById("myCanvas").toDataURL("image/png");
    img = img.replace(/^data:image\/(png|jpg);base64,/, "")

    // Sending the image data to Server
    $.ajax({
        type: 'POST',
        url: '/upload',              // /new 
        data: '{ "imageData" : "' + img + '" }',
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (msg) {
        // On success code
        }
    });
}

接下来是在服务器端获取上传的图片数据,方法是使用 request.json['imageData'],然后把它存储到数据库里。

img = request.json['imageData'] # Store this in DB (use blob)

撰写回答