0

我们在测试时发现了这一点,一台机器设置为 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++ 手,我有点想念类型安全。

4

1 回答 1

0

这是 Python 的一个方面,与 Django本身无关。

通过为函数参数定义默认值,您并没有消除位置参数的概念——您只是可以在调用函数时不指定所有参数。@mVChr 说在调用例程时需要养成使用参数名称的习惯是正确的,特别是当调用例程存在固有的歧义时。

您还可以考虑使用两个独立的例程,它们的名称安静地清楚地标识了它们预期的参数类型。

于 2013-01-26T00:58:14.623 回答