Description

Python 2.6 supports named tuples. Information about field names is stored in the tuple class, so there's no overhead like in dictionaries.
I propose to use them in querysets instead of values() / values_list().

I like the idea of introducing a QuerySet that returns named tuples! Not crazy about the name, but I can't think of a better one at the moment.

Can you create an actual .patch file, include unit tests and include a fallback namedtuple implementation for our Python 2.4/2.5 users? A good place for that would be in django/utils/datastructures.py.

Why the namedtuples API? Is there some reason values_list should not return namedtuples directly? It should be backwards compatible, as index based fetching still work. I believe there will not be any serious performance impact.

If the performance is acceptable, then raw cursors should return named tuples, too. That would be a really nice addition for raw SQL users. But of course, this is another ticket's problem.

I have a very quick implementation of returning namedtuples from .values_list(). The patch seems to be backwards compatible, that is, all tests pass.

The performance penalty seems to be about 20% for one-field values_list() call. It is a good question if that is acceptable. I guess yes as namedtuples are _much_ nicer than regular tuples. On the other hand the main use case for values_list is performance.

The results are using SQLite to fetch 200 objects with one field containing a four char value, and then additional fields containing NULLs. values_list with one field gives the 20% performance penalty, 5 fields gives 15% penalty. Notably in-memory SQLite with fields containing practically no data is pretty much the worst-case. I guess the real-world penalty will be in 5%-20% range depending on use case. My opinion is that getting namedtuples is worth it.

I guess similar performance penalty would be paid if cursors were to return named tuples directly, and that is even tougher call to make. Cursors are even more performance critical, and every query made by Django would need to pay the penalty. Although when creating model instance for example that penalty would be hidden by overhead of model.__init__.

It is of course possible to add the .namedtuples() API, but then we have three things doing nearly the same thing, and two doing exactly the same thing from user perspective.