База данных SQLite3 изначально поддерживает только ограниченный набор типов Python. Чтобы использовать другие типы Python с SQLite, необходимо адаптировать их к одному из поддерживаемых типов модуля sqlite3 для SQLite: одному из None, int, float, str, bytes.
Есть два способа включить модуль sqlite3 для адаптации пользовательского типа Python к одному из поддерживаемых.
Предположим, есть такой класс:
class Point: def __init__(self, x, y): self.x, self.y = x, y
Теперь необходимо сохранить точку в одном столбце SQLite. Сначала нужно выбрать один из поддерживаемых типов SQLite, который будет использоваться для представления точки. Давайте просто используем str и разделим координаты точкой с запятой. Затем нужно дать классу метод __conform__(self, protocol), который должен возвращать преобразованное значение. Протокол protocol параметров будет PrepareProtocol.
import sqlite3 class Point: def __init__(self, x, y): self.x, self.y = x, y def __conform__(self, protocol): if protocol is sqlite3.PrepareProtocol: return "%f;%f" % (self.x, self.y) con = sqlite3.connect(":memory:") cur = con.cursor() p = Point(4.0, -3.2) cur.execute("select ?", (p,)) print(cur.fetchone()[0]) con.close()
Другая возможность - создать функцию, которая преобразует тип в строковое представление, а потом ее зарегистрировать с помощью sqlite3.register_adapter().
import sqlite3 class Point: def __init__(self, x, y): self.x, self.y = x, y def adapt_point(point): return "%f;%f" % (point.x, point.y) sqlite3.register_adapter(Point, adapt_point) con = sqlite3.connect(":memory:") cur = con.cursor() p = Point(4.0, -3.2) cur.execute("select ?", (p,)) print(cur.fetchone()[0]) con.close()
Модуль sqlite3 имеет два адаптера по умолчанию для встроенных в Python типов datetime.date() и datetime.datetime(). Теперь предположим, что необходимо хранить объекты datetime.datetime не в формате ISO, а в виде метки времени Unix.
import sqlite3 import time, datetime def adapt_datetime(ts): return time.mktime(ts.timetuple()) sqlite3.register_adapter(datetime.datetime, adapt_datetime) con = sqlite3.connect(":memory:") cur = con.cursor() now = datetime.datetime.now() cur.execute("select ?", (now,)) print(cur.fetchone()[0]) con.close()