web-dev-qa-db-fra.com

sqlalchemy.orm.exc.UnmappedInstanceError dans la fiole

J'ai lu les documents SQLAlchemy, mais je ne les comprends pas. L'erreur (UnmappedInstanceError) indique que quelque chose n'est pas mappé. Qu'est-ce qui n'est pas cartographié? Je ne reçois vraiment pas sqlalchemy et je veux recommencer à utiliser du sqlite nu, mais beaucoup de gens le recommandent, alors j'ai pensé que je devrais l'apprendre. Voici la 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

Voici le code applicable:

@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'))
14
user2986242
q = request.form['name']
# do for 12 more fields
db.session.add(q)

request.form['name'] renverra une valeur unicode. Ensuite, vous faites ...

db.session.add(q)

Le but de la session est de garder une trace d'entités (objets Python), et non de valeurs unicode individuelles comme vous semblez vouloir le faire (voir ici pour plus d'informations sur le fonctionnement de la session). Ainsi, vous devriez ajouter des objets ayant un mappage (tel qu'un objet User, comme indiqué dans la section "Mappage" du tutoriel ORM ), mais vous transmettez en réalité une simple valeur Unicode.

Ce que vous utilisez n'est qu'une partie de SQLAlchemy: l'ORM (Object-Relational Mapper). L'ORM essaiera de faire des choses comme vous permettre de créer un nouvel objet python et de générer automatiquement le code SQL en "ajoutant" l'objet à la session.

a = MyEntity()
session.add(a)
session.commit() # Generates SQL to do an insert for the table that MyEntity is for

N'oubliez pas que vous pouvez utiliser SQLAlchemy sans utiliser la fonctionnalité ORM. Vous pouvez simplement faire db.execute('INSERT...', val1, val2) pour remplacer votre SQL déjà "nu". SQLAlchemy vous fournira le pooling de connexion, etc. (bien que si vous utilisez SQLite, vous ne vous souciez probablement pas du pooling de connexion).

Si vous voulez comprendre Flask-SQLAlchemy, je vous recommanderais tout d’abord de comprendre le fonctionnement de SQLAlchemy (en particulier du côté ORM) en l’essayant à l’aide de scripts simples (comme indiqué dans le tutorials . Ensuite, vous comprendrez comment travaillerait avec cela.

6
Mark Hildreth

Lorsque vous ajoutez un objet non modèle à la session, vous obtenez UnmappedInstanceError.

Dans votre cas, q était probablement une chaîne unicode et non un objet de modèle. (Il semble que vous utilisiez Python 2.x car dans Python 3.x, str dira), il s'agissait de la ligne de la cause première de 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)
8
Devy

Si vous changez de base de données, voir: Vous devez indiquer à quel élément de l'objet vous souhaitez changer. Voir ci-dessous:

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()

Comme vous pouvez le voir dans l'objet 'client', nous avons "nom" parmi d'autres informations à l'intérieur de l'objet. Nous voulons changer directement le 'nom' uniquement, vous devez donc vous y adresser. (Nom du client)


Si vous ajoutez un nouvel élément à la base de données: Ici, lorsque vous ajoutez une nouvelle valeur à la base de données avec orm, vous devez spécifier l'élément dans l'objet qui reçoit les données. )

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

J'espère que cela pourra aider. 

0
Andy