user14272
user14272

Reputation: 119

Flask + sqlalchemy + marshmallow - Error on relationship - One to Many

Why this code returns an error?

Error: When initializing mapper Mapper|Pessoa|pessoa, expression 'Imovel' failed to locate a name ("name 'Imovel' is not defined").

from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow

db=SQLAlchemy()
ma=Marshmallow()

class Pessoa(db.Model):
    __tablename__ = 'pessoa'
    idLocal= db.Column(db.Integer, primary_key=True)
    Nome=db.Column(db.String(100), default=u'')
    imovelList = db.relationship("Imovel", back_populates="PessoaList")
    def get_id(self):
        return self.idLocal

class PessoaSchema(ma.ModelSchema):
    class Meta: model = Pessoa

class Imovel(db.Model):
    __tablename__ = 'imovel'
    idLocal= db.Column(db.Integer, primary_key=True)
    CodigoImovel=db.Column(db.String(30), default=u'')
    idPessoa = db.Column(db.Integer, db.ForeignKey('pessoa.idLocal'))
    PessoaList = db.relationship("Pessoa", back_populates="imovelList")
    def get_id(self):
        return self.idLocal

class ImovelSchema(ma.ModelSchema):
    class Meta: model = Imovel

Upvotes: 0

Views: 542

Answers (1)

steve
steve

Reputation: 2638

You have an 'order of declaration' issue. Relationships are initialized immediately when their Mappers are constructed when the relationship is defined with a String. But when you define the relationship on "Imovel" you have yet to declare a Mapper called "Imovel". The Imovel Mapper or class is defined a couple lines after that.

So you could move the Imovel Mapper above the Pessoa Mapper, except then you would get the exact same error as you are also building a relationship from Imovel to Pessoa.

So instead you want to declare your relationship using a callable function that will return the "Imovel" Mapper. This function will typically only be called after all Mappers are constructed. Thus by using a lambda function we can ensure the relationship is not invoked until you have had a chance to setup the Imovel class.

In practice, to fix this error, replace this line

imovelList = db.relationship("Imovel", back_populates="PessoaList")

with this

imovelList = db.relationship(lambda: Imovel, back_populates="PessoaList")

Upvotes: 3

Related Questions