From: Denis Laxalde Date: Fri, 12 Feb 2021 14:55:14 +0000 (+0100) Subject: Document row factories X-Git-Tag: 3.0.dev0~106^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34126291be20687f6a35fe0503dde7de7068ca58;p=thirdparty%2Fpsycopg.git Document row factories We document the row_factory argument of *Connection.execute() as well as the row_factory attribute on Connection. We add a new page in advanced section explaining the concepts of row factories, providing examples and documenting built-in row factories. --- diff --git a/docs/advanced/index.rst b/docs/advanced/index.rst index 0bd6d587a..31e391692 100644 --- a/docs/advanced/index.rst +++ b/docs/advanced/index.rst @@ -5,6 +5,7 @@ Advanced topics :maxdepth: 1 :caption: Contents: + ../row-factories ../adaptation ../prepared ../copy diff --git a/docs/connection.rst b/docs/connection.rst index 04a7842a7..698183106 100644 --- a/docs/connection.rst +++ b/docs/connection.rst @@ -65,7 +65,7 @@ The `!Connection` class .. note:: You can use :ref:`with conn.cursor(): ...` to close the cursor automatically when the block is exited. - .. automethod:: execute(query, params=None, prepare=None) -> Cursor + .. automethod:: execute(query, params=None, prepare=None, row_factory=None) -> Cursor :param query: The query to execute. :type query: `!str`, `!bytes`, or `sql.Composable` @@ -74,7 +74,9 @@ The `!Connection` class :param prepare: Force (`!True`) or disallow (`!False`) preparation of the query. By default (`!None`) prepare automatically. See :ref:`prepared-statements`. - :type prepare: `!bool` + :param row_factory: Optional row factory to form result's row. See + :ref:`row-factories` for details. + :type row_factory: `Callable[[Cursor], Callable[[Sequence[Any]], Any]]` The cursor is what returned calling `cursor()` without parameters. The parameters are passed to its `~Cursor.execute()` and the cursor is @@ -83,6 +85,12 @@ The `!Connection` class See :ref:`query-parameters` for all the details about executing queries. + .. autoattribute:: row_factory + :annotation: RowFactory + + Writable attribute to control how result's rows are formed. + See :ref:`row-factories` for details. + .. rubric:: Transaction management methods For details see :ref:`transactions`. @@ -203,7 +211,7 @@ The `!AsyncConnection` class .. note:: You can use ``async with conn.cursor() as cur: ...`` to close the cursor automatically when the block is exited. - .. automethod:: execute(query, params=None, prepare=None) -> AsyncCursor + .. automethod:: execute(query, params=None, prepare=None, row_factory=None) -> AsyncCursor .. automethod:: commit .. automethod:: rollback diff --git a/docs/row-factories.rst b/docs/row-factories.rst new file mode 100644 index 000000000..eae335be3 --- /dev/null +++ b/docs/row-factories.rst @@ -0,0 +1,60 @@ +.. currentmodule:: psycopg3 + +.. index:: row factories + +.. _row-factories: + +Row factories +============= + +Cursor's `fetch*` methods return tuples of column values by default. This can +be changed to adapt the needs of the programmer by using custom row factories. + +A row factory is a callable that accepts a cursor object and returns another +callable accepting a `values` tuple and returning a row in the desired form. +This can be implemented as a class, for instance: + +.. code:: python + + class DictRowFactory: + def __init__(self, cursor): + self.cursor = cursor + + def __call__(self, values): + fields = (c.name for c in self.cursor.description) + return dict(zip(fields, values)) + +or as a plain function: + +.. code:: python + + def dict_row_factory(cursor): + def make_row(values): + fields = (c.name for c in cursor.description) + return dict(zip(fields, values)) + + return make_row + +These can then be used by specifying a `row_factory` argument in +`Connection.connect()`, `Connection.cursor()`, `Cursor.execute()` and +`Connection.execute()` or by writting to `Connection.row_factory` attribute. + +.. code:: python + + conn = psycopg3.connect(row_factory=DictRowFactory) + cur = conn.execute("SELECT first_name, last_name, age FROM persons") + person = cur.fetchone() + print(f"{person['first_name']} {person['last_name']}") + +Later usages of `row_factory` override earlier definitions; for instance, +the `row_factory` specified at `Connection.connect()` can be overridden by +passing another value at `Connection.cursor()`. + +Available row factories +----------------------- + +Module `psycopg3.rows` contains available row factories: + +.. currentmodule:: psycopg3.rows + +.. autofunction:: dict_row