База данных 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()