Hmm, I can't think of a reason it uses dir() instead of hasattr(). I
tracked down the change to changeset 2432 on the magic-removal branch
in February 2006:
http://code.djangoproject.com/changeset/2432
Do all the unit tests still pass if you convert it to a hasattr()?
Adrian
--
Adrian Holovaty
holovaty.com | djangoproject.com
David, looks like your test DB is not created in utf-8 charset. Try
these two settings:
http://www.djangoproject.com/documentation/settings/#test-database-charset
Looks like you might need to set TEST_DATABASE_CHARSET='utf-8'. Django's
tests need UTF-8 (or something comparable) to test a few and
unfortunately MySQL's default charset seems to be Latin1 on most
installations. See docs/tests.txt or docs/settings.txt for details.
Malcolm
--
On the other hand, you have different fingers.
http://www.pointy-stick.com/blog/
It might not always be available, was one concern (although I suspect
not a real problem). The other one is that if you're running your
application's tests, you should be using the same encoding that your
production database is using, which might not be UTF-8.
Malcolm
--
Atheism is a non-prophet organization.
http://www.pointy-stick.com/blog/
class CustomMetaclass(ModelBase):
def __new__(cls, name, attrs, bases):
# Skip Django initialization if we are looking at CustomModel
try:
CustomModel
except NameError:
return type.__new__(cls, name, bases, attrs)
...
# Do Django initialization
return super(CustomMetaclass, cls).__new__(cls, name, bases, attrs)
class CustomModel(Model):
__metaclass__ = CustomMetaclass
class MyModel(CustomModel):
...
This worked perfectly before the r7098 optimizations, but now I get
"AttributeError: type object 'CustomModel' has no attribute '_meta'" (in
django/db/models/base.py, line 46) :
42 # Build complete list of parents
43 for base in parents:
44 if base is not Model:
45 new_class._meta.parents.append(base)
46 new_class._meta.parents.extend(base._meta.parents)
CustomModel is not Model, but as it is not initialized by Django it does
not have a _meta attribute either (and I don't want it initialized by
Django because it would create a *_custommodel table, plus the extra
unnecessary initializations).
The quick hack was to add a fake _meta to CustomModel :
class CustomModel(Model):
class _meta:
parents = ()
fields = ()
__metaclass__ = CustomMetaclass
I understand this may be a corner case, but the ability to extend
Django's initialization is really nice, and this optimization makes the
code ugly on the applications side (and was there really a need for an
optimization ? "1-1.5s per 10000 models" does not tell much on what has
been gained, what is the total time needed to initialize 10000 models ?)
As I mentioned in the ticket you filed, if CustomModel is meant to be a
Model subclass, you must have a _meta attribute. That's one of the
things about being a Model subclass: you have a _meta. You want to do
the equivalent of creating an int subclass that doesn't support integer
operations. It's not like it's a huge problem for you to adjust to this.
Also, keep in mind that model subclassing is entirely unsupported in
Django at the moment and changes are undergoing to support it. That
might well involve a few other internal shufflings (ModelBase.__new__
gets simpler, in fact), although I don't think they will affect this
particular case.
I don't feel that Django should have to work around the fact that people
are creating things pretending to be a Model subclass that don't meet
the requirements. The fact that it worked before was accidental, not
some feature of the construct (go back over the history of that method
and you can see that 30 months ago it didn't support much subclassing
ability at all and we have slowly been tidying it up and in [7098]
continued that trend by removing some more unneeded code).
[...]
> I understand this may be a corner case, but the ability to extend
> Django's initialization is really nice, and this optimization makes the
> code ugly on the applications side (and was there really a need for an
> optimization ? "1-1.5s per 10000 models" does not tell much on what has
> been gained, what is the total time needed to initialize 10000 models ?)
The change wasn't made solely because of the speed benefits. Models just
aren't created that often for it to be the most relevant factor (__new__
is only called import time normally). It was also made because it makes
the code cleaner, particularly with some upcoming further changes in
there.
Anyway, I'm not going to comment any further here, since I obviously
think the change is a plus. I want to here what some of the other
maintainers think.
Malcolm
--
For every action there is an equal and opposite criticism.
http://www.pointy-stick.com/blog/
I've changed it to a hasattr() approach in [7716]; on further reflection
this seemed more in line with a duck-typing approach.
Regards,
Malcolm
--
If it walks out of your refrigerator, LET IT GO!!
http://www.pointy-stick.com/blog/
Cheers,
Luper