Могу ли я таким образом вызвать функцию в SQLAlchemy?

db.session.query(User).update({'spotify_date':format_date(User.spotify_date)})
db.session.commit()

Здесь я попытался вызвать функцию format_date() для форматирования даты в столбце spotify_date таблицы отношений User.

Вот пользовательские модели

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    spotify_id = db.Column(db.String(20), unique=False, nullable=True)
    spotify_token = db.Column(db.String(20), unique=False, nullable=True)
    spotify_date = db.Column(db.String(20), unique=False, nullable=True)

И функция fomate_date() и вызов функции

from app import app, db, User

def format_date(date):
    """Format date to local format: dd-mm-yyyy
    
    Args:
        date (String): spotify_date
    
    Returns:
        string: date formatted in local

    Examples:
    >>> formate_date('2020-07-18')
    '18-07-2020'
    
    """
    dateList = date.split('-')
    dateList.reverse()

    return '-'.join(dateList)



db.session.query(User).update({'spotify_date':format_date(User.spotify_date)})
db.session.commit()

После этого у меня возникло исключение:

AttributeError: ни объект 'InstrumentedAttribute', ни объект 'Comparator', связанные с User.spotify_date, не имеют атрибута 'split'

В любом случае, как я могу правильно сделать это в запросе SQLAlchemy? Спасибо

P.S: Я использую базу данных Postgresql; функция - это функция Python, а не функция базы данных. Спасибо.

2
Houy Narun 17 Июл 2020 в 19:26

1 ответ

Лучший ответ

Если вы хотите сделать запрос UPDATE, который обновляет несколько строк, вам необходимо передать одно выражение (значение, функцию и т. Д.) В этот запрос. Функция Python не работает, потому что ваша база данных не знает эту конкретную функцию. Итак, вам нужно преобразовать вашу функцию format_date в выражение SQL и передать его вашему запросу:

from app import db, User

format_date = (db.func.substr(User.spotify_date, 9, 2) + '-' +
               db.func.substr(User.spotify_date, 6, 2) + '-' +
               db.func.substr(User.spotify_date, 1, 4))
db.session.query(User).update({'spotify_date': format_date}, synchronize_session=False)
db.session.commit()

Функция SQLAlchemy func позволяет вам использовать внутренние функции базы данных. Функция format_date в чистом SQL выглядит так:

SUBSTR("user"."spotify_date", 9, 2) || '-' || SUBSTR("user"."spotify_date", 6, 2) || '-' || SUBSTR("user"."spotify_date", 1, 4)

Также обратите внимание, что эта функция работает для столбцов типа String (VARCHAR). Для типа DateTime (TIMESTAMP) все будет иначе.


Чтобы применить функцию Python к значениям из таблицы, вам необходимо сначала получить эти значения. После этого вам нужно применить функцию и выполнить ОБНОВЛЕНИЕ для каждой отдельной строки. Как вы заметили, это будет довольно долго.

1
Sergey Shubin 23 Июл 2020 в 12:09