__slot__ like behaviour for Model classes?

347 views
Skip to first unread message

jorjun

unread,
Aug 31, 2007, 7:26:09 AM8/31/07
to Django developers
Glad though I am that Python has dynamic class attributes, when it
comes to Django Models, some more discipline could be useful,
especially when a product is in maintenance phase, IMO.

I recently added the code below to my model definition and it saved me
a bunch of time after some model evolution, by making sure that old
attributes were not still being referred to in templates.

Wondering whether code like this could be implemented as decorator or
activated as an optional meta attribute to the Django Model class if
found generally useful, ideally it should be possible to detail any
exceptions for those rare cases when the usual Python dynamic run-time
attribute get/set behaviour is still required?
It would be good to hear informed comments, in case I am completely
wrong headed about this...

def __setattr__(self, name, value):
if name.startswith("_") or name.endswith("id") or \
name in self.__slots__:
self.__dict__[name] = value
else:
raise AttributeError, "Illegal set attempt: %s = %s" %
(name, value)

def __getattr__(self, name):
if name.startswith("_") or name.endswith("id") or \
name in self.__slots__:
if self.__dict__.has_key(name):
return self.__dict__[name]
else:
return getattr(super(Listing, self), name)
else:
raise AttributeError, "Illegal get attempt: %s" %name

Jay Parlar

unread,
Aug 31, 2007, 10:56:35 AM8/31/07
to django-d...@googlegroups.com


Just so you know, the intended behaviour of __slots__ is *not* to
restrict dynamic behaviours. It is simply an optimization technique.
It is generally considered "wrong" to use __slots__ for restrictive
purposes, as it goes against the grain of Python.

And I'm not sure if you've actually run that code, or if I'm missing
something, but if a class does have __slots__ defined on it, then, by
definition, the class will *not* have a __dict__ attribute.

Jay P.

jorjun

unread,
Sep 1, 2007, 2:21:28 PM9/1/07
to Django developers
Thanks for replying Jay

Yeah, I thought that adding __slots__ to the Django model would be
enough, since the __dict__ is meant to get replaced by accessors as
you have pointed out. But I have been running the code, and it hasn't
worked as expected, that is why I had to write the __getattr__. It
would be interesting to know why, and I read the comment about
__slots__ being of questionable value.

But I disagree with __slots__ being justified purely for optimization
purposes. If you have a model that is better for having some of its
attributes moved to a different model (resulting in database changes,
migration issues and my sympathy), then you have a problem in that
references to the 'old plan' still work, but unintentionally rather
than being reflective of Python's 'dynamic' nature. IMO (and probably
counter intuitively) it would add to the flexibility of the language
to allow Django Models especially, to be tightened up so that any new
regime you might impose will be respected. Or more practically
speaking, so that petty errors can be resolved quickly during unit
testing. But this issue doesn't raise its head until you have tried to
evolve your Django model and gotten further along in the process than
prototyping and are running in a production environment.

--Peter

Jay Parlar

unread,
Sep 2, 2007, 11:07:16 AM9/2/07
to django-d...@googlegroups.com
On 9/1/07, jorjun <jor...@gmail.com> wrote:
> But I disagree with __slots__ being justified purely for optimization
> purposes.

Disagree all you want, but this is what Guido Van Rossum, creator of
Python and BDFL, had to say about it:

"__slots__ is a terrible hack with nasty, hard-to-fathom side effects
that should only be used by programmers at grandmaster and wizard
levels. Unfortunately it has gained an enormous undeserved popularity
amongst the novices and apprentices, who should know better than to
use this magic incantation casually."

Jay P.

alex....@gmail.com

unread,
Jul 11, 2022, 9:53:17 AM7/11/22
to Django developers (Contributions to Django itself)
I realize this thread is 15 years old, but I actually ran into this issue the other day. I was running a custom migration with a RunPython function, where rather than typing:

my_model.message = '...'

I accidentally wrote:

my_model.mesage = '...'

The migration ran successfully, so I ended up just losing all the data from the old column that I was trying to use to populate the new field with data and then drop. Thankfully this was just on my dev database, but it would have been nice if Django had been able to recognize that 'mesage' isn't a valid field name on the model and raise an error. This way the migration would have failed and the transaction would have been reverted, rather than committing without any of the data I was trying to save into the new column.

Alex

Reply all
Reply to author
Forward
0 new messages