Fields as Descriptors

The real 'data' would end up either in name-mangled instance members, or in a private dictionary.

When accessed via the class, they would return themselves. eg
Reporter.name would be a field class you can inspect. This would make introspection as in the admin easier.

When accessed via the instance, they would return a representation of the value they
hold. This could be

the simple data instance from the private dict that was fetched from the db.

a lazily computed value, eg a BLOB field which would be fetched from the db on first access, not at initial load time, or a ForeignKey relationship that hasn't been loaded yet.
For a ForeignKey,

article.get_reporter()
article.reporter_id

would change to:

article.reporter
article.reporter.id

ForeignKeys and other related fields would place another descriptor on the related class.
When accessed via the instance, this would return a lazy collection object. It will act like a set
(an ordered one if there is an ordering involved).

This would also support other methods in favour of the get_related_list things.

The collection supports the appropriate collection protocols : It acts as a set, with ordering
if there is an ordering in the underlying query. The query is only done when a collection protocol is used.
Sometimes, multiple queries will be used to save traffic, eg if you access reporter.article_set[10000:10020] and then reporter.article_set[:20].

Other methods of a similar style are also possible.

.add would add a new instance of the related class to the collection.
This would register a callback so that it would be written to the db when .save() is called on the parent object.

This looks a bit odd because of the clear call . In reality, most of the time you don't want to replace a whole set of many-to-manys, so the new api is more convenient than the old one. The methods are precisely those of a Python 2.4 built in set.

Query Syntax

In further discussions about this idea, it seemed consistent that both the manager ( Person.objects ) and relationship end points, (reporter.articles) would act as lazy sets of instances (base class QuerySet?) , with these 'refinement' methods on them (filter, order_by, etc).

Query sets would be combinable with the standard set operators, which would be less clumsy than the current complex= query syntax.
eg
ar_list = Person.objects.get_list(complex=Q(name_startswith="R")|Q(name_startswith="A") )
goes to (idiosyncratically)

The reason we avoided this in the initial design of Django is that we wanted it to be clear when an action would result in a database query being executed. This explicitness makes it easier to optimise your code - it's obvious when an action will result in an extra query, making it clearer when you should store results in a local variable for later use. -- Simon Willison .

I think the mailing list is better for discussions, but I don't think that you need to worry about the local variable thing. You can still save things in a local variable, exactly as before. The only change is that things will not actually be fetched until required. After that, they will be cached. -- Robert Wittams