#python #postgresql #sqlalchemy #flask-sqlalchemy #circular-dependency
#python #postgresql #sqlalchemy #flask-sqlalchemy #циклическая зависимость
Вопрос:
Я новичок в Flask-SQLAchemy и SQLAlchemy, пытаюсь понять ограничения и взаимосвязи, поэтому я написал приведенный ниже код из хорошо известного примера базы данных. Каждый экземпляр Employee принадлежит отделу, и у каждого экземпляра отдела есть сотрудник в качестве менеджера. Оба внешних ключа, dnumber и mgrssn, не могут быть нулевыми. Код работает так, как ожидалось, и создает точно такую же схему, созданную кодом SQL.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql psycopg2://postgres:<password>@<host>:<port>/<dbname>'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Employee(db.Model):
__tablename__ = 'employee'
__table_args__ = ({"schema": "public"})
ssn = db.Column('ssn', db.String(11), primary_key=True)
fname = db.Column('fname', db.String(20), nullable=False)
lname = db.Column('lname', db.String(20), nullable=False)
bdate = db.Column('bdate', db.Date, nullable=False)
address = db.Column('address', db.String(50), nullable=False)
sex = db.Column('sex', db.String(1), nullable=False)
salary = db.Column('salary', db.Integer, nullable=False)
# Relationship (1-1): Employee --has-> Employee (as supervisor)
superssn = db.Column('superssn',
db.String(11),
db.ForeignKey('public.employee.ssn', name='supervisor'))
emp_supervisor = db.relationship('Employee', backref=db.backref(name='supervisor', remote_side=ssn), lazy='dynamic')
# Relationship (1-M): Department --has-> Employee(s)
dnumber = db.Column('dnumber',
db.Integer,
db.ForeignKey("public.department.dnumber", name='department'),
nullable=False)
# Relationship (1-M): Employee(manager) --manages-> Department(s)
dep_manager = db.relationship('Department', backref='manager', lazy='dynamic', foreign_keys="[Department.mgrssn]", post_update=True)
class Department(db.Model):
__tablename__ = "department"
__table_args__ = ({"schema": "public"})
dnumber = db.Column('dnumber', db.Integer, primary_key=True)
dname = db.Column('dname', db.String(50), unique=True, nullable=False)
# Relationship (1-M): Employee(manager) --manages-> Department(s)
mgrssn = db.Column('mgrssn',
db.String(11),
db.ForeignKey("public.employee.ssn", name='manager'),
nullable=False,
unique=True)
mgrstartdate = db.Column('mgrstartdate', db.Date, nullable=False)
# Relationship (1-M): Department --has-> Employee(s)
employees = db.relationship('Employee', backref='department', lazy='dynamic', foreign_keys="[Employee.dnumber]", post_update=True)
def __repr__(self):
return f'<Department> {self.dname}'
Проблема начинается, когда я пытаюсь вставить строки, в то время как я не могу найти правильный порядок создания и обновления экземпляров с учетом ограничений. Я провел несколько тестов, таких как приведенный ниже, который возвращает очевидную ошибку:
«ошибка sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) нулевое значение в столбце «dnumber» нарушает ненулевое ограничение ПОДРОБНО: ошибка строки содержит (888-66-5555, Джеймс Э., Борг, 1937-11-10, 450 Стоун,. Хьюстон, Техас, Массачусетс, 55000, 888-66-5555, null).«
if __name__ == "__main__":
db.create_all()
emp1 = Employee(ssn='888-66-5555', fname='James E', lname='Borg', bdate='1937-11-10', address='450 Stone,. Houston, TX', sex='M', salary=55000, superssn='888-66-5555')
dep1 = Department(dnumber=5, dname='Research', mgrstartdate='1998-05-22')
emp1.department = dep1
db.session.add(emp1)
dep1.manager = emp1
db.session.add(dep1)
db.session.commit()
Используя синтаксис SQL с WITH xxx AS INSERT
помощью I, я могу управлять порядком инструкций insert. Однако я не могу найти, как добиться этого в SQLAlchemy, когда внешние ключи существуют в обеих связанных таблицах?