3

I have been developing a webserver application using Flask. So far, I created a small framework, where the users can draw some boxes in a image, using canvas and javascript. I keep the boxes information in a vector in javascript as well as the image information. However, all this data must be submitted and stored in a database the server side. Therefore, I have a button to submit all this content, but I have no idea how to retrieve the javascript data I have, i.e.: boxes and image information.

Is it possible to get the javascript information to submit like that? I have come up with some ideas such as printing the information in hidden HTML elements, or, maybe, using AJAX for sending the information to the server, but I don't think those are the "correct" methods for dealing with this problem in Flask. So, does anyone have a idea. Here follow part of my code that may seem relevant for understanding my problem:

Models.py: My classes here are a little different: Blindmap=Image, Label=boxes. My database is modelled using 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)

My controllers information:

@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 Answers 2

3
+50

Try 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
        }
    });
}

Rest is get uploaded image data at server side using request.json['imageData'] and store it in database.

img = request.json['imageData'] # Store this in DB (use blob)
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, I have tried to make as you wrote there. I created my function getting my data from the JS variables and I put everything on a json and passed to data in the ajax function. However, I have an error. It is said in the console: BAD REQUEST. What can that be? I'm not expert in ajax. Here follow the network: X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Referer: localhost:5000/new Pragma: no-cache Host: localhost:5000 Content-Type: application/json;charset=utf-8 Content-Length: 245 Connection: keep-alive
Ops, I discovered my problem. I had a problem in the json I was trying to post. Now I can retrieve all the information, create my classes and save in the database. Thank you very much. It worked Perfectly. :) :)
1

What you have to do is to use AJAX, the technique to "asynchronously" send requests and get responses from a server after the page is loaded on the client's browser, using JavaScript. AJAX, in fact, stands for Asynchronous JavaScript And XML (even though it doesn't necessarily have to be neither completely asynchronous, nor you must resort to XML as a data exchange format). This is the standard way to access Web APIs, such as the one you crafted with Flask by exposing the ability to retrieve and persiste objects in your backend through URLs (the ones represented the the routes).

Modern browsers consistently expose the XMLHttpRequest constructor (MDN documentation) that can be used to create objects that allow the page to communicate with your Web server once it's loaded.

To improve cross-browser compatibility and code maintainability, you can resort to JavaScript frameworks that "wrap" the XMLHttpRequest with their own abstractions. I've been productively using jQuery for years for this purpose. In particular, in your case you would need the jQuery.ajax method (or, for POST operations, it's shorthand jQuery.post).

However I'll give you a small example of how to perform such request using vanilla JS so that you can understand what's going on in the browser even when using a framework:

// 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...');

Refer to MDN for more details about using the XMLHttpRequest.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.