Get rid of model modules?

50 views
Skip to first unread message

Simon Willison

unread,
Sep 15, 2005, 12:46:27 PM9/15/05
to django-d...@googlegroups.com
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

Matthew Marshall

unread,
Sep 15, 2005, 8:15:01 AM9/15/05
to django-d...@googlegroups.com
+1

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

Robert Wittams

unread,
Sep 15, 2005, 3:51:34 PM9/15/05
to django-d...@googlegroups.com
Sounds like a really good idea to me. It would certainly be best to get
the big changes in all in a short period.

Eugene Lazutkin

unread,
Sep 15, 2005, 5:19:14 PM9/15/05
to django-d...@googlegroups.com
"Robert Wittams" <rob...@wittams.com> wrote in
message news:dgcjc5$dvr$1...@sea.gmane.org...
>
> Sounds like a really good idea to me. It would certainly be best to get
> the big changes in all in a short period.

Yep. If it should be done, it should be done now before official release.

Thanks,

Eugene



Adrian Holovaty

unread,
Sep 15, 2005, 6:10:51 PM9/15/05
to django-d...@googlegroups.com
On 9/15/05, Simon Willison <swil...@gmail.com> wrote:
> from django.models.blog import Blog, Entry
>
> Blog.get_list()
> Blog.get_object()
> Entry.get_iterator()

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

Sune Kirkeby

unread,
Sep 15, 2005, 6:45:32 PM9/15/05
to django-d...@googlegroups.com
On 9/15/05, Simon Willison <swil...@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 ;)

/s

ima...@gmail.com

unread,
Sep 16, 2005, 9:44:26 AM9/16/05
to Django developers
The one thing I don't like is that I cannot add decorators like
classmethod. For instance, this method:

@classmethod
def clsmethod(cls):
print "HERE in", cls

Blows up like this for me:

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.

Simon Willison

unread,
Sep 16, 2005, 10:05:28 AM9/16/05
to django-d...@googlegroups.com

On 15 Sep 2005, at 23:10, Adrian Holovaty wrote:

> 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.

Cheers,

Simon

Joseph Kocherhans

unread,
Sep 16, 2005, 10:16:36 AM9/16/05
to django-d...@googlegroups.com
On 9/15/05, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 9/15/05, Simon Willison <swil...@gmail.com> wrote:
> > from django.models.blog import Blog, Entry
> >
> > Blog.get_list()
> > Blog.get_object()
> > Entry.get_iterator()
>
> 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.

Joseph

Adrian Holovaty

unread,
Sep 16, 2005, 12:21:08 PM9/16/05
to django-d...@googlegroups.com
On 9/15/05, Sune Kirkeby <sune.k...@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 Holovaty

unread,
Sep 16, 2005, 12:25:31 PM9/16/05
to django-d...@googlegroups.com
On 9/16/05, ima...@gmail.com <ima...@gmail.com> wrote:
> The one thing I don't like is that I cannot add decorators like
> classmethod. For instance, this method:
>
> @classmethod
> def clsmethod(cls):
> print "HERE in", cls
>
> Blows up like this for me:
>
> 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.

Martin Maney

unread,
Sep 16, 2005, 12:46:47 PM9/16/05
to django-d...@googlegroups.com
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

Simon Willison

unread,
Sep 16, 2005, 12:51:09 PM9/16/05
to django-d...@googlegroups.com

On 15 Sep 2005, at 23:45, Sune Kirkeby wrote:

> 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.

Cheers,

Simon

Eugene Lazutkin

unread,
Sep 16, 2005, 3:19:38 PM9/16/05
to django-d...@googlegroups.com
+1 from me.

"Adrian Holovaty" <holo...@gmail.com> wrote
in message news:6464bab05091...@mail.gmail.com...

Jacob Kaplan-Moss

unread,
Sep 16, 2005, 4:47:05 PM9/16/05
to django-d...@googlegroups.com
On Sep 16, 2005, at 2:19 PM, Eugene Lazutkin wrote:
> +1 from me.

Me three.

Additionally, we should make the manipulator methods work the same way::

class MyModel(meta.Model)
f = meta.CharField(...)

class META:
...

class MODULE:
...

class MANIPULATOR:
...

Very nice and symmetrical!

Jacob

Adrian Holovaty

unread,
Sep 16, 2005, 11:22:12 PM9/16/05
to django-d...@googlegroups.com
On 9/16/05, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:
> class MyModel(meta.Model)
> f = meta.CharField(...)
>
> class META:
> ...
>
> class MODULE:
> ...
>
> class MANIPULATOR:
> ...

Meta? Module? Manipulator? Marvelous.
Reply all
Reply to author
Forward
0 new messages