Below I have defined SQLAlchemy models for a table containing companies and a table containing contracts. Each company can have many contracts while each contract can belong to one company (one to many relationship). This relationship is modelled by contracts = db.relationship('ContractModel', backref=db.backref('company', lazy=True))
.
Models:
class CompanyModel(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True, nullable=False) industry = db.Column(db.String(64), nullable=False) password = db.Column(db.String(64), nullable=False) company_logo_path = db.Column(db.String(255), unique=True, nullable=False) contracts = db.relationship('ContractModel', backref=db.backref('company', lazy=True)) class ContractModel(db.Model): id = db.Column(db.Integer, primary_key=True) length = db.Column(db.Integer, nullable=False) value = db.Column(db.Float, nullable=False) description = db.Column(db.Text, nullable=False) location = db.Column(db.String(50), nullable=False) date = db.Column(db.Date, nullable=False) company_name = db.Column(db.String, db.ForeignKey(CompanyModel.name), nullable=False) status = db.Column(db.Boolean, default=True, nullable=False)
I try to append a company to a contract (which links them) after creating a contract:
contract = ContractModel(length=args['contract_length'], value=args['contract_value'], description=args['contract_description'], location=args['contract_location'], status=args['contract_status'], date=datetime.utcnow(), company_name=args['company_name']) associated_company = CompanyModel.query.filter_by(name=args['company_name']).first() # Company name resides in args['company_name']. This company has already been added to the database. contract.company.append(associated_company)
This gives the error: AttributeError: 'NoneType' object has no attribute 'append'
where the culprit line is: contract.company.append(associated_company)
. Why am I not able to append a company to a contract even though their one to many relationship is defined? Did I model the relationship incorrectly?
Advertisement
Answer
Your relationship is correct. The only problem is that contract.company
is currently an undefined attribute of your newly-created ContractModel
object. You are then trying to append another object to this ‘NoneType’. The correct way to specify which company with which to link a contract would be by modifying the contract.company
attribute instead of adding to it. You could even do this in two lines if you define associated_company
before creating a new contract:
associated_company = CompanyModel.query.filter_by(name=args['company_name']).first() contract = ContractModel(length=args['contract_length'], value=args['contract_value'], description=args['contract_description'], location=args['contract_location'], status=args['contract_status'], date=datetime.utcnow(), company_name=args['company_name'], company=associated_company)