From 5ed9616a09679f1b03fd4421c5adbfab17c74efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dra=C5=BEen=20Odoba=C5=A1i=C4=87?= Date: Sat, 29 Aug 2015 16:54:51 +0200 Subject: [PATCH] [1.8.x] Fixed #25326 -- Added namedtuple example for executing custom SQL. Backport of 5ab65ca5c900557f508f62a260f9ea53d9d93f37 from master --- docs/topics/db/sql.txt | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt index 09d6c12eb83..dc40d1f3e6a 100644 --- a/docs/topics/db/sql.txt +++ b/docs/topics/db/sql.txt @@ -275,28 +275,50 @@ alias:: cursor = connections['my_db_alias'].cursor() # Your code here... -By default, the Python DB API will return results without their field -names, which means you end up with a ``list`` of values, rather than a -``dict``. At a small performance cost, you can return results as a -``dict`` by using something like this:: +By default, the Python DB API will return results without their field names, +which means you end up with a ``list`` of values, rather than a ``dict``. At a +small performance and memory cost, you can return results as a ``dict`` by +using something like this:: def dictfetchall(cursor): - "Returns all rows from a cursor as a dict" + "Return all rows from a cursor as a dict" desc = cursor.description return [ dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall() ] -Here is an example of the difference between the two:: +Another option is to use :func:`collections.namedtuple` from the Python +standard library. A ``namedtuple`` is a tuple-like object that has fields +accessible by attribute lookup; it's also indexable and iterable. Results are +immutable and accessible by field names or indices, which might be useful:: + + from collections import namedtuple + + def namedtuplefetchall(cursor): + "Return all rows from a cursor as a namedtuple" + desc = cursor.description + nt_result = namedtuple('Result', [col[0] for col in desc]) + return [nt_result(*row) for row in cursor.fetchall()] + +Here is an example of the difference between the three:: >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2"); >>> cursor.fetchall() - ((54360982L, None), (54360880L, None)) + ((54360982, None), (54360880, None)) >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2"); >>> dictfetchall(cursor) - [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}] + [{'parent_id': None, 'id': 54360982}, {'parent_id': None, 'id': 54360880}] + + >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2"); + >>> results = namedtuplefetchall(cursor) + >>> results + [Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)] + >>> results[0].id + 54360982 + >>> results[0][0] + 54360982 Connections and cursors -----------------------