One thing that feels a little strange about Django is the way that
model classes (with many in a single application file) turn in to
modules when that application is installed. The reason for this is
the module level methods associated with a model: blogs.get_list(),
blogs.get_object() etc.
An alternative could be to have those as class methods added to the
model classes themselves:
from django.models.blog import Blog, Entry
Blog.get_list()
Blog.get_object()
Entry.get_iterator()
etc...
This is an enormous change to Django, but I feel it would improve the
usability of the framework. It would eliminate the need for
module_name, module_constants and exceptions (all could be handled as
class properties instead). It could also lead to the removal of
BlogNotFoundException and friends - they could be replaced by
exceptions based on nested classes: Blog.NotFound.
I started thinking about this while trying to work out how to define
a new module-level method - I realised that class methods might be a
much better fit for that kind of thing.
It's a really big change, even bigger than the recent model syntax
change because this change would mean re-writing views as well.
Still, I thought it would be worth bringing up here for discussion.
I have become used to this, but it was (perhaps needlessly) confusing at first.
In a way, this wouldn't be as big as the model syntax change, as it could be done incrementally. There is nothing (AFAIK) stopping using both methods for a while.
MWM
On Thursday 15 September 2005 04:46 pm, Simon Willison wrote:
> One thing that feels a little strange about Django is the way that
> model classes (with many in a single application file) turn in to
> modules when that application is installed. The reason for this is
> the module level methods associated with a model: blogs.get_list(),
> blogs.get_object() etc.
> An alternative could be to have those as class methods added to the
> model classes themselves:
> from django.models.blog import Blog, Entry
> Blog.get_list()
> Blog.get_object()
> Entry.get_iterator()
> etc...
> This is an enormous change to Django, but I feel it would improve the
> usability of the framework. It would eliminate the need for
> module_name, module_constants and exceptions (all could be handled as
> class properties instead). It could also lead to the removal of
> BlogNotFoundException and friends - they could be replaced by
> exceptions based on nested classes: Blog.NotFound.
> I started thinking about this while trying to work out how to define
> a new module-level method - I realised that class methods might be a
> much better fit for that kind of thing.
> It's a really big change, even bigger than the recent model syntax
> change because this change would mean re-writing views as well.
> Still, I thought it would be worth bringing up here for discussion.
> One thing that feels a little strange about Django is the way that > model classes (with many in a single application file) turn in to > modules when that application is installed. The reason for this is the
> module level methods associated with a model: blogs.get_list(), > blogs.get_object() etc.
> An alternative could be to have those as class methods added to the > model classes themselves:
> from django.models.blog import Blog, Entry
> Blog.get_list()
> Blog.get_object()
> Entry.get_iterator()
> etc...
> This is an enormous change to Django, but I feel it would improve the > usability of the framework. It would eliminate the need for > module_name, module_constants and exceptions (all could be handled as > class properties instead). It could also lead to the removal of > BlogNotFoundException and friends - they could be replaced by > exceptions based on nested classes: Blog.NotFound.
> I started thinking about this while trying to work out how to define a
> new module-level method - I realised that class methods might be a much
> better fit for that kind of thing.
> It's a really big change, even bigger than the recent model syntax > change because this change would mean re-writing views as well. Still,
> I thought it would be worth bringing up here for discussion.
> Cheers,
> Simon Willison
Sounds like a really good idea to me. It would certainly be best to get
the big changes in all in a short period.
I have a natural aversion to class methods like that. To me, it makes
more sense for a *module* to contain functions that return instances,
than for a *class* to have methods that return instances of that same
class. It's one of the things I don't like about SQLObject (which, of
course, has things that I do like -- but class-method use isn't one of
'em).
In the above example, Blog.get_object() returns a Blog instance, and
each Blog instance has a get_object() method. That feels awkward,
messy and ugly, in my opinion.
Adrian
-- Adrian Holovaty
holovaty.com | djangoproject.com | chicagocrime.org
On 9/15/05, Simon Willison <swilli...@gmail.com> wrote:
> One thing that feels a little strange about Django is the way that
> model classes (with many in a single application file) turn in to
> modules when that application is installed. The reason for this is
> the module level methods associated with a model: blogs.get_list(),
> blogs.get_object() etc.
I actually like that way it works right now, at least the generated
model-interfaces as modules.
Although, I very much would like to see a nicer way of describing
what should go into the modules (the "_module_"-prefix,
"module_constants" and "exceptions" all look funny, and feel
unnatural to me...)
> usability of the framework. It would eliminate the need for
> module_name, module_constants and exceptions (all could be handled as
> class properties instead).
Couldn't django auto-fill much of module_constants
from co_freevars in the code-objects of the methods? That
would be nice.
Hmm... And, how about a "MODULE_LEVEL"-class inside
the model-classes, whose attributes are copied into the
genereated module? I think I like that more than class-attributes,
since it emphasises that black magic is occuring behind the
scenes (I think it helped me to understand what was really
going on, that the behind-the-scenes magic was not too
hidden...)
Then one could put "def gnah" in MODULE_LEVEL instead of
"def _module_gnah" in the model, also exceptions and the
module_constants that cannot be auto-deduced could
go in there...
> exceptions based on nested classes: Blog.NotFound.
I would much rather see an all lowercase prefix, both because
"Blog" is one more key-press than "blog", but also becasue I just
think "blog" looks nicer ;)
File "C:\www\django\core\meta\__init__.py", line 490, in __new__ assert callable(v), "%r is an invalid model parameter." % k AssertionError: 'clsmethod' is an invalid model parameter.
I am also not able to create a 'memoize' decorator for caching method results in an instance. Instead, I either have to do the "if _cache_blah: return _cache_blah" pattern in each method I want cacheable or call out to a non-model function that can be memoized but using a global LRU dictionary.
While I see both Simon's and Adrian's side in this debate, if my problem can only be solved by removing the existing modules "magic" then I have to vote +1 for Simon because I think it is bad form not to support decorators in django models.
If this suggestion does get approved, is there a way we can make the current modules methods still work by simply having them reference the class methods, rather than forcing a re-write of existing applications? The old pattern could simply be deprecated.
> I have a natural aversion to class methods like that. To me, it makes
> more sense for a *module* to contain functions that return instances,
> than for a *class* to have methods that return instances of that same
> class. It's one of the things I don't like about SQLObject (which, of
> course, has things that I do like -- but class-method use isn't one of
> 'em).
> In the above example, Blog.get_object() returns a Blog instance, and
> each Blog instance has a get_object() method. That feels awkward,
> messy and ugly, in my opinion.
I can't say I disagree with you there - module level methods that
return classes do seem more pythonic - which means it becomes a trade- off: is the uglyness of class methods returning instances worth
putting up with for the convenience of reducing the amount of weird
magic in the models files? Personally I tend towards preferring less
magic in the models in exchange for a slightly less pretty feeling API.
> I have a natural aversion to class methods like that. To me, it makes
> more sense for a *module* to contain functions that return instances,
> than for a *class* to have methods that return instances of that same
> class. It's one of the things I don't like about SQLObject (which, of
> course, has things that I do like -- but class-method use isn't one of
> 'em).
> In the above example, Blog.get_object() returns a Blog instance, and
> each Blog instance has a get_object() method. That feels awkward,
> messy and ugly, in my opinion.
It does to me as well, but I think the benefits might outweight the
costs in this case. It occured to me that it's not necessarily the
module/class distiction that bothers me, but the naming:
MyObj.get_object() vs. myobjs.get_object(). If this change goes
through I might try something like
from django.models.myapp import MyObj as myobjs
I've never really used aliases though... I suspect there might be some
gotchas there.
Also, I don't know if the proposed change would help, but being able
to use properties in my classes would be great.
On 9/15/05, Sune Kirkeby <sune.kirk...@gmail.com> wrote:
> Couldn't django auto-fill much of module_constants
> from co_freevars in the code-objects of the methods? That
> would be nice.
That's possible, but I've hesitated to do so because models have a lot
of global variables available to them -- basically, a lot of random
crap such as the other model classes. Is it better to grab more or
fewer global variables? I've had a preference for fewer, but I'd love
to get other opinions on it.
> Hmm... And, how about a "MODULE_LEVEL"-class inside
> the model-classes, whose attributes are copied into the
> genereated module? I think I like that more than class-attributes,
> since it emphasises that black magic is occuring behind the
> scenes (I think it helped me to understand what was really
> going on, that the behind-the-scenes magic was not too
> hidden...)
> Then one could put "def gnah" in MODULE_LEVEL instead of
> "def _module_gnah" in the model, also exceptions and the
> module_constants that cannot be auto-deduced could
> go in there...
That's a great idea. It would make it more explicit that module-level
magic is happening, and it would remove the need for the ugly
"_module" prefixes. And it can be backwards-compatible (for at least a
short while), because we could support both approaches. What do people
think?
Adrian
-- Adrian Holovaty
holovaty.com | djangoproject.com | chicagocrime.org
> File "C:\www\django\core\meta\__init__.py", line 490, in __new__
> assert callable(v), "%r is an invalid model parameter." % k
> AssertionError: 'clsmethod' is an invalid model parameter.
> I am also not able to create a 'memoize' decorator for caching method
> results in an instance. Instead, I either have to do the "if
> _cache_blah: return _cache_blah" pattern in each method I want
> cacheable or call out to a non-model function that can be memoized but
> using a global LRU dictionary.
I would certainly call this a bug. Model methods should be able to
have decorators. I've filed a ticket at
http://code.djangoproject.com/ticket/522 and will try to work on the
fix this weekend.
Adrian
-- Adrian Holovaty
holovaty.com | djangoproject.com | chicagocrime.org
On Fri, Sep 16, 2005 at 12:21:08PM -0400, Adrian Holovaty wrote:
> On 9/15/05, Sune Kirkeby <sune.kirk...@gmail.com> wrote:
> > Then one could put "def gnah" in MODULE_LEVEL instead of
> > "def _module_gnah" in the model, also exceptions and the
> > module_constants that cannot be auto-deduced could
> > go in there...
> That's a great idea. It would make it more explicit that module-level
> magic is happening, and it would remove the need for the ugly
> "_module" prefixes. And it can be backwards-compatible (for at least a
> short while), because we could support both approaches. What do people
> think?
It's concise, seems to be more consistent, and it saves typing without
being more obscure (I think - simple case looks good). What's not to
like?
Belated comment on the module vs. class thing: IMO this is more
syntactic sugar, and even for that it's more "how much sugar?" rather
than sugar or not. Both ways there's a namespace that contains
functions that are class factories. One way its capitalized, the other
it's not. :-) De gustibus...
-- The dualist evades the frame problem - but only because
dualism draws the veil of mystery and obfuscation
over all the tough how-questions -- Daniel C. Dennett
> Hmm... And, how about a "MODULE_LEVEL"-class inside
> the model-classes, whose attributes are copied into the
> genereated module? I think I like that more than class-attributes,
> since it emphasises that black magic is occuring behind the
> scenes (I think it helped me to understand what was really
> going on, that the behind-the-scenes magic was not too
> hidden...)
I really like that idea - it's much more obvious than the _model_ thing.
> Then one could put "def gnah" in MODULE_LEVEL instead of
> "def _module_gnah" in the model, also exceptions and the
> module_constants that cannot be auto-deduced could
> go in there...
That's a great idea. It would make it more explicit that module-level
magic is happening, and it would remove the need for the ugly
"_module" prefixes. And it can be backwards-compatible (for at least a
short while), because we could support both approaches. What do people
think?