Как создать сопоставление столбцов, которое по-прежнему работает в запросах SQL? - PullRequest
0 голосов
/ 29 мая 2020

У меня очень простая модель, как показано ниже:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), index=True)
    role = db.Column(db.String(64))

, а затем простой запрос, который я использую в моем представлении для фильтрации пользователей по ролям:

roles = list(map(str, query_params.get('roles', [])))
User.query.filter(User.role.in_(roles))

Роли начните с заглавной буквы («Директор», «Менеджер» и т. д. c ...), и я хочу добавить сопоставление к столбцу, которое возвращает его в нижнем регистре. Я думал, что column_property() или @hybrid_property сработают, но я либо ошибаюсь, либо делаю ошибку в реализации.

Я пробовал эти изменения:

@hybrid_property
def role_tag(self):
    return self.role.lower()

User.query.filter(User.role_tag.in_(roles))

Свойство действительно возвращает значение в нижнем регистре, но оно не работает в запросе, вызывающем это исключение:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with User.profile_role has an attribute 'lower'

Затем я попытался изменить модель как таковую:

role_tag = column_property(role.lower())

, которые вместо этого вызывают другое исключение непосредственно в модели.

AttributeError: Neither 'Column' object nor 'Comparator' object has an attribute 'lower'

Я понимаю, что проблема связана с тем, как они работают, на уровне класса или экземпляра. .. Но, в конце концов, я не смог найти правильную реализацию для моего варианта использования.

1 Ответ

1 голос
/ 01 июня 2020

Решение состоит в том, чтобы определить поведение отдельно для контекста экземпляра и класса или Python и SQL context:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), index=True)
    role = db.Column(db.String(64))

    @hybrid_property
    def role_tag(self):
        return self.role.lower()

    @role_tag.expression
    def role_tag(cls):
        return db.func.lower(cls.role)
...