Я пытаюсь воссоздать свою базу данных, используя SQLAlchemy и Flask.
Я создал все модели, но теперь у меня есть некоторые проблемы с отношениями между моделями. При вставке или обновлении объекта Flask возвращает следующее сообщение об ошибке:
File "C:\Users\Lenna\SchoolMi\api-server-v4\venv\lib\site-packages\sqlalchemy\ext\declarative\clsregistry.py", line 326, in __call__
x = eval(self.arg, globals(), self._dict)
File "<string>", line 1, in <module>
# ext/declarative/clsregistry.py
AttributeError: 'Table' object has no attribute 'id'
Сообщение об ошибке ссылается на отношение active_channel в классе профиля и указывает, что у класса канала нет атрибута id. Однако я уже определил этот атрибут в классе ObjectWithDefaultProps. После проверки файла SQL в браузере SQL атрибут id действительно присутствует в объекте Channel.
Моим первым предположением была неверная конфигурация внешнего ключа, поэтому я попытался изменить внешний ключ:
active_channel = db.relationship("Channel", foreign_keys="Channel.id")
вместо
active_channel = db.relationship("Channel", foreign_keys="channel.id")
К сожалению, это не сработало , Ошибка меняется на следующее:
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on
relationship Profile.active_channel - there are no foreign keys linking these tables. Ensure that referencing
columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression. //
Werkzeug Debugger
Я рассмотрел аспекты полиморфизма в SQLAlchemy и подумал, что он может иметь какое-то отношение к mapperargs , но не смог выяснить правильный способ реализации этого.
В моем коде у меня есть следующие классы:
Мои сущности происходят из нескольких объектов, которые представляют общие атрибуты или отношения.
class Profile(db.Model, ObjectWithDefaultProps, ObjectWithAvatar, ObjectWithNotificationProfile):
__tablename__ = "profile"
firebase_uid = db.Column(db.String, unique=True, nullable=False, primary_key=True)
username = db.Column(db.String, unique=True, nullable=False)
firstname = db.Column(db.String, nullable=False)
lastname = db.Column(db.String, nullable=False)
about = db.Column(db.String)
score = db.Column(db.Integer)
email = db.Column(db.String, nullable=False)
active_channel_id = db.Column(db.Integer, db.ForeignKey("channel.id"))
active_channel = db.relationship("Channel", foreign_keys="channel.id")
Channel.py
class Channel(db.Model, ObjectBase, ObjectWithAvatar, ObjectWithName, ProfileLinkedObject):
__tablename__ = "channel"
description = db.Column(db.String)
can_add_tags = db.Column(db.Boolean, default=False, nullable=False)
can_public_join = db.Column(db.Boolean, default=False, nullable=False)
from database.provider import db
from datetime import datetime
class ObjectWithDefaultProps:
deleted = db.Column(db.Boolean, nullable=False, default=False)
date_modified = db.Column(db.DateTime, default=datetime.utcnow)
date_added = db.Column(db.DateTime, onupdate=datetime.utcnow)
from database.provider import db
from database.extensions.object_with_color import ObjectWithColor
class ObjectWithAvatar(ObjectWithColor):
image_url = db.Column(db.String)
from database.provider import db
class ObjectWithColor:
color_index = db.Column(db.Integer, default=0)
from database.provider import db
from sqlalchemy.ext.declarative import declared_attr
class ObjectWithNotificationProfile:
auto_follow_questions = db.Column(db.Integer)
auto_follow_answers = db.Column(db.Integer)
auto_follow_comments = db.Column(db.Integer)
auto_follow_questions_on_comment = db.Column(db.Integer)
auto_follow_questions_on_answer = db.Column(db.Integer)
auto_follow_answers_on_comment = db.Column(db.Integer)
send_new_data_notification = db.Column(db.Boolean)
send_new_members_notification = db.Column(db.Boolean)
@declared_attr
def question_event_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_event_preferences.id"))
@declared_attr
def question_event_preferences(cls):
return db.relationship("CustomEventPreferences", foreign_keys="custom_event_preferences.id")
@declared_attr
def answer_event_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_event_preferences.id"))
@declared_attr
def answer_event_preferences(cls):
return db.relationship("CustomEventPreferences", foreign_keys="custom_event_preferences.id")
@declared_attr
def comment_event_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_event_preferences.id"))
@declared_attr
def comment_event_preferences(cls):
return db.relationship("CustomEventPreferences", foreign_keys="custom_event_preferences.id")
@declared_attr
def question_tagging_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_tagging_preferences.id"))
@declared_attr
def question_tagging_preferences(cls):
return db.relationship("CustomTaggingPreferences", foreign_keys="custom_tagging_preferences.id")
@declared_attr
def answer_tagging_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_tagging_preferences.id"))
@declared_attr
def answer_tagging_preferences(cls):
return db.relationship("CustomTaggingPreferences", foreign_keys="custom_tagging_preferences.id")
@declared_attr
def comment_tagging_preferences_id(cls):
return db.Column(db.Integer, db.ForeignKey("custom_tagging_preferences.id"))
@declared_attr
def comment_tagging_preferences(cls):
return db.relationship("CustomTaggingPreferences", foreign_keys="custom_tagging_preferences.id")