Without a concrete base class:>>> Animal.objects.all() SELECT ... FROM animal;With a concrete base class:>>> Animal.objects.all() SELECT ... FROM "animal" INNER JOIN "baseobject" ON ("animal"."baseobject_ptr_id" = "baseobject"."id")
What you want:>>> BaseObject.objects.all()[<Animal: Frog>, <Vegetable: Carrot>, <Mineral: Gold>, ...]What you get:>>> BaseObject.objects.all()[<BaseObject: 1>, <BaseObject: 2>, <BaseObject: 3>, ...]
So maybe you try something like:def get_some_of_everything(): qs = BaseObject.objects.all() for obj in qs: for cls in BaseObject.__subclasses__(): try: obj = cls.objects.get(baseobject_ptr=obj) break except cls.DoesNotExist: continue yield obj
“Our site worked ﬁne in development and testing, and was working wonderfully for the ﬁrst few months.“But we just added a bunch more data, and now our homepage takes 27 seconds to load.”
“But… but… everything really does need a creation date!”So give everything a creation date.
“Do the simplest thing that could possibly work.” — Simon Willison
If you must get fancy: Abstract base classes don’t suﬀer from these performance problems. Denormalize into a UI-ordered auxiliary model. Non-relational databases work particular well here (I like SOLR).
Those who do notunderstand PYTHONPATHare doomed to failure.
$ ./manage.py shell>>> import dashboard.models>>> dashboard.models<module dashboard.models from /Users/jacob/Projects/djdash/dashboard/models.pyc>>>> import djdash.dashboard.models>>> djdash.dashboard.models<module djdash.dashboard.models from /Users/jacob/Projects/djdash/../djdash/dashboard/models.pyc>>>> djdash.dashboard.models.Metric is dashboard.models.MetricFalse
You might have an import issue if…“Hey, many-to-many relations don’t show up in the admin.”“What’s up with these import errors when I deploy under mod_wsgi?”“Grrr… assertRaises doesn’t work!”
Django is wrong! (I’m sorry.)
Fixing import madness1. Use non-project-relative imports (import app.models, not import project.app.models).2. Use relative imports (from . import x) where possible (see http://bit.ly/pep328).3. Stop using manage.py.
Delete manage.py?$ django-‐admin.py shell -‐-‐pythonpath=`pwd` -‐-‐settings=settings.local>>> import dashboard.models>>> import djdash.dashboard.modelsTraceback (most recent call last)...ImportError: No module named djdash.dashboard.models
Don’t do this …INSTALLED_APPS += [p for p in os.listdir(BASE) if os.path.isdir(p)]
… or this …urlpatterns = patterns(, ...)for app in settings.INSTALLED_APPS: if not app.startswith(django): p = url(^%s/ % app, include(%s.urls) % app) urlpatterns += patterns(, p)
… or this.MIDDLEWARE_CLASSES = [...]def callback(arg, dirname, fnames): if middleware.py in fnames: m = %s.middleware % os.path.split(dirname)[-‐1]) MIDDLEWARE_CLASSES.append(m)os.path.walk(BASE, callback, None)
Python’s design is predicated on the proposition that code is more often read than written.