我们在测试时发现了这一点,一台机器设置为 MyISAM 作为默认引擎,另一台机器设置为 InnoDB 作为默认引擎。我们有类似于以下的代码
class StudyManager(models.Manager):
def scored(self, school=None, student=None):
qset = self.objects.all()
if school:
qset = qset.filter(school=school)
if student:
qset = qset.filter(student=student)
return qset.order_by('something')
问题代码如下所示:
print Study.objects.scored(student).count()
这意味着“学生”被视为学校。这通过了 MyISAM 的测试,因为 student.id == school.id 因为 MyISAM 无法进行回滚并完全重新创建每个测试(重置自动增量 id 字段)。InnoDB 捕获了这些错误,因为回滚显然不会重置自动增量字段。
id
问题是,在测试期间,由于所有模型都有一个字段,因此可能有许多其他错误由于鸭子类型而未被捕获。我担心排队的对象(在生产或测试中)上的 id 会导致问题/无法找到错误。
我可以像这样添加断言:
class StudyManager(models.Manager):
def scored(self, school=None, student=None):
qset = self.objects.all()
if school:
assert(isinstance(school, School))
qset = qset.filter(school=school)
if student:
assert(isinstance(student, Student))
qset = qset.filter(student=student)
return qset.order_by('something')
但这看起来很糟糕,而且需要做很多工作(回去改造)。在调试模式下它也更慢。
我考虑过可以将模型的 id 字段强制转换为 model_id
(student_id for Student, school_id for School) 这样学校就没有 student_id 的想法,这只涉及指定主键字段,但 django 有一个.pk 中的快捷方式所以我猜这可能在所有情况下都没有帮助。
有没有更优雅的解决方案来捕捉这种错误?作为一个老 C++ 手,我有点想念类型安全。