我有一个非常简单的应用程序,它连接到具有外键约束的数据库。这是从 SQL Server 生成的脚本
表脚本
/****** Object: Table [dbo].[challenge_topic] Script Date: 7/28/2021 10:50:01 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[challenge_topic](
[id] [int] IDENTITY(1,1) NOT NULL,
[theme_id] [int] NOT NULL,
[leader_level_id] [int] NOT NULL,
[title] [nvarchar](250) NOT NULL,
[description] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_challenge_topics] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[challenge_topic] WITH CHECK ADD CONSTRAINT [FK__ChallengeTopics__ID] FOREIGN KEY([theme_id])
REFERENCES [dbo].[topic_theme] ([id])
GO
ALTER TABLE [dbo].[challenge_topic] CHECK CONSTRAINT [FK__ChallengeTopics__ID]
GO
ALTER TABLE [dbo].[challenge_topic] WITH CHECK ADD CONSTRAINT [FK__LeaderType__ID] FOREIGN KEY([leader_level_id])
REFERENCES [dbo].[leader_level] ([id])
GO
ALTER TABLE [dbo].[challenge_topic] CHECK CONSTRAINT [FK__LeaderType__ID]
GO
为了连接到这个表,我有一个带有 SQLAlchemy 的 Flask API。我检查了我的 API 以查看它是否返回了我想要的数据,并且确实如此。但是,当我运行 pytest 时,我遇到了外键约束的问题。我得到的错误如下:
ERROR app/services/challengeTopicService_test.py::test_get_all - sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Could not drop object 'challenge_topic' because it is referenced by a FOREIGN KEY constraint. (3726) (SQLExecDirectW)")
这是我的测试 挑战TopicService_test.py
from app.services.challengeTopicService import ChallengeTopicService
from app.challengeTopic.challengeTopicModel import ChallengeTopic
from flask_sqlalchemy import SQLAlchemy
from typing import List
from app.test.fixtures import app, db
from app.challengeTopic.challengeTopicModel import ChallengeTopic
def test_get_all(db: SQLAlchemy):
topic1 : ChallengeTopic = ChallengeTopic(id = 100,
theme_id = 1,
leader_level_id = 1,
title = "Personal Improvement",
description = "The challenge of learning to be more like your 'ideal self.' This includes developing confidence, being a better listener, improving flexibility, dealing more effectively with conflict, and being less reactive.")
topic2: ChallengeTopic = ChallengeTopic(id = 101,
theme_id = 1,
leader_level_id = 1,
title = "Frustrations with People and Time",
description = "The challenge of feeling frustrated with others and overwhelmed with inefficiencies. This includes providing considerable guidance to direct reports, overcoming resistant attitudes, and adjusting communication and feedback styles to work with different people more effectively.")
db.session.add(topic1)
db.session.add(topic2)
db.session.commit()
results: List[ChallengeTopic] = ChallengeTopicService.get_all()
assert len(results) == 2
assert topic1 in results and topic2 in results
def test_get_by_id(db: SQLAlchemy):
topic1 : ChallengeTopic = ChallengeTopic(id = 100,
theme_id = 1,
leader_level_id = 1,
title = "Personal Improvement",
description = "The challenge of learning to be more like your 'ideal self.' This includes developing confidence, being a better listener, improving flexibility, dealing more effectively with conflict, and being less reactive.")
topic2: ChallengeTopic = ChallengeTopic(id = 101,
theme_id = 1,
leader_level_id = 1,
title = "Frustrations with People and Time",
description = "The challenge of feeling frustrated with others and overwhelmed with inefficiencies. This includes providing considerable guidance to direct reports, overcoming resistant attitudes, and adjusting communication and feedback styles to work with different people more effectively.")
db.session.add(topic1)
results: List[ChallengeTopic] = ChallengeTopicService.get_by_id(100)
assert len(results) == 1
assert topic1 in results and topic2 not in results
挑战主题服务.py
from app.leaderLevel.leaderLevelModel import LeaderLevel
from typing import List
from app.challengeTopic.challengeTopicModel import ChallengeTopic
class ChallengeTopicService():
@staticmethod
def get_all(**filters) -> List[ChallengeTopic]:
filters_ = {k:v for k, v in filters.items() if k in ['short_name'] and v is not None}
if len(filters_) == 0:
return ChallengeTopic.query.all()
else:
## Fetch the leader data from LeaderType table to fetch the ID
leader_level_result = LeaderLevel.query.filter_by(**filters_)
leader_level_id = None
for item in leader_level_result:
leader_level_id = item.id
return ChallengeTopic.query.filter_by(leader_level_id = leader_level_id)
@staticmethod
def get_by_id(challenge_topic_id: int) -> ChallengeTopic:
topics = ChallengeTopic.query.get(challenge_topic_id)
return topics
挑战主题模型.py
from sqlalchemy.orm import relationship
from app import db
class ChallengeTopic(db.Model):
"""
Challenge Topics and description obtained from the Challenge Ladder.
"""
__tablename__="challenge_topic"
id = db.Column(db.Integer(), primary_key=True)
description = db.Column(db.String())
title = db.Column(db.String(250))
theme_id = db.Column(db.Integer(), db.ForeignKey('topic_theme.id'), nullable=False)
leader_level_id = db.Column(db.Integer(), db.ForeignKey('leader_level.id'), nullable=False)
leader_level = relationship("LeaderLevel", back_populates="challenge_topics")
topic_theme = relationship("TopicTheme", back_populates="challenges")
persona = relationship("PersonaChallengeAssociation", back_populates="challenges")
def __repr__(self):
return '<Challenge Topic %s>' % self.topic
那么,避免 SQLAlchemy 遇到外键约束的错误并解决这个问题的最佳方法是什么?