'sqlalchemy.orm.exc.UnmappedInstanceError in flask

I have been reading the SQLAlchemy docs, but I don't understand them. The error (UnmappedInstanceError) says something isn't mapped. What isn't mapped? I really don't get sqlalchemy and I want to go back to using naked sqlite, but so many people recommend this, so I thought I should learn it. Here is the traceback:

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)

File "C:\Users\Me\repos\mandj2\app\views.py", line 170, in add_manentry
db.session.add(q)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\sqlalchemy\orm\scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)

File "C:\Users\Me\repos\mandj\venv\lib\site-packages\sqlalchemy\orm\session.py", line 1452, in add
raise exc.UnmappedInstanceError(instance)

UnmappedInstanceError: Class '__builtin__.unicode' is not mapped

Here is the applicable code:

@app.route('/addm', methods=['POST'])
def add_mentry():
    if not session.get('logged_in'):
        abort(401)
    form = MForm(request.form)
    filename = ""
    if request.method == 'POST':
        cover = request.files['cover']
        if cover and allowed_file(cover.filename):
            filename = secure_filename(cover.filename)
            cover = cover.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

    q = request.form['name']
    # do for 12 more fields
    db.session.add(q)
    db.session.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('moutput'))


Solution 1:[1]

When you are adding a non-model-object into the session, you will be getting UnmappedInstanceError.

In your case, q was probably an unicode string, not a model object. (It appears that you are using Python 2.x because in Python 3.x, it will say str), this was the line of the root cause for UnmappedInstanceError: Class '__builtin__.unicode' is not mapped:

  File "C:\Users\Me\repos\mandj2\app\views.py", line 170, in add_manentry
  db.session.add(q)

Solution 2:[2]

If you are changing database see: You have to address to what item in the object you want to change. See below:

client = session.query(Clients).filter_by(id=client_id).one()
if request.method == 'POST':
    new_name = request.form['form_name']
    client.name = new_name
    session.add(client)
    session.commit()

As you can see in the 'client' object, we have "name" among other info inside the object. We want to directly change 'name' only, therefore you need to address to it. (client.name)


If you are adding new thing to database: Here when you add a new value to the database with orm, you need to specify the item in the object that is receiving the data. in this case (Client.name)

    if request.method == 'POST':
        new_name = request.form['form_name']
        name = Clients(name=new_name)
        session.add(name)
        session.commit()

Hope that helps.

Solution 3:[3]

I came across a problem like this. In the following code below, I tried to delete some posts:

@app.route('/categorydeletion', methods=['POST'])
def deletecategory():
    name_of_category = request.form['categoryname']
    category_to_be_deleted = Category.query.filter_by(name=name_of_category).first()
    accompained_post = Posts.query.filter_by(category_id=category_to_be_deleted.id).all()
    if category:`enter code here`
        db.session.delete(category_to_be_deleted)
        db.session.delete(accomapained_post)
        db.session.commit()
        return 'successful

But I was getting the same error sqlalchemy.orm.exc.UnmappedInstanceError

So my fix was this below:

@app.route('/categorydeletion', methods=['POST'])
def deletecategory():
    name_of_category = request.form['categoryname']
    category_to_be_deleted = Category.query.filter_by(name=name_of_category).first()
    accompained_post = Posts.query.filter_by(category_id=category_to_be_deleted.id).all()
    if category:
        db.session.delete(category_to_be_deleted)

        def delete_accomapained_post():
            for i in accompained_post:
                db.session.delete(i)

        delete_accomapained_post()
        db.session.commit()
        return 'successful'

As @devy pointed out, you work with python objects; with the first scenario I was working with a python list.

But in the second scenario, I had to create a function delete_accomapained_post() to loop through the list to access the Python objects that I want to work with.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 pppery