Jinja2/Flask:当列表包含 None 时排序错误

Jinja2/Flask: sort-error when list contains None's

我使用 Flask/Jinja2 将简单模型渲染为 table。一切正常,但如果我尝试对 None 进行排序和属性,我会得到

TypeError: unorderable types: NoneType() < NoneType()

我实现了 __lt____gt__ 方法来对我的对象进行排序。

我的第一个 class 是一个任务-class。它有一个指向 Person-class 的外键。我想按 Person-class 排序,但是 None 是一个合法的 person 状态。

模板片段

 {% for t in tasks | sort(attribute=sort_on) %}

models.py 片段:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(300),nullable=False)
    username = db.Column(db.String(300),nullable=False,unique=True)
    tasks = db.relationship('Task', backref='resource', lazy='dynamic')

    def __lt__(self,other):
        if other == None:
            return True
        return self.name.__lt__(other.name)

    def __gt__(self,other):
        if other == None:
            return False
        return self.name.__gt__(other.name)


class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(300),nullable=False)
    text = db.Column(db.Text)
    prio = db.Column(db.Integer)
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'),nullable=False)
    planned_days = db.Column(db.Integer)
    done = db.Column(db.Integer)
    state_id = db.Column(db.Integer, db.ForeignKey('state.id'),nullable=False)
    issue = db.Column(db.String(100))

有人知道我该如何解决这个问题吗?

这里的问题是您的列表中有 多个 None 值要排序,而 None 对象本身不可排序:

>>> sorted([None, None])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < NoneType()

技巧就是提供决胜局:

>>> sorted([(None, 1), (None, 0)])
[(None, 0), (None, 1)]

此处列表包含正在排序的元组;当元组的第一个元素相等时,根据下一个元素打破平局。

在 Jinja2 中,您不能轻松地直接执行此操作,因为内置 sort filter 不允许您按任意键函数排序。

理想情况下,您确实应该在 SQL 代码中执行此操作,而不是在模板或 Python 代码中:

if sort_on == 'person':
    query = Task.query.join(Task.person_id).order_by(Person.name)

但在 Python 代码中,您可以提取元组(决胜局是 Task 属性):

sorted(tasks, key=lambda t: (t.person and t.person.name, task.name))