On Tue, Feb 1, 2011 at 9:22 AM, David Greisen <[email protected]> wrote:
> Dear List,
>
> This is my first time writing to the list. I've been working with Django for
> the last two years and recently started hacking on Django itself.
>
> For a while I have felt restricted by the fact that I cannot replace the
> user model.

You're not the first person with this complaint.

> I think this problem could be solved by making models pluggable. I realize
> that this has been proposed before
> (http://groups.google.com/group/django-developers/browse_thread/thread/2dd8fb9ea1fd3763/ef7db33f2fe713a3).

The idea of pluggable models has been proposed before. The thread you
reference isn't the most recent incarnation of that discussion,
either:

http://groups.google.com/group/django-developers/browse_thread/thread/c8e2397fefd85030
http://groups.google.com/group/django-developers/browse_thread/thread/c8921795bc7868af

The app-refactor that is referenced in those discussions was Arthur
Koziel's GSoC project last year; merging the results of this project
into trunk is one of the big ticket items that has a lot of support
for the 1.4 timeframe.

> I have been thinking about how to bring the advantages of a pluggable
> architecture to django's models without any of the disadvantages described
> in the thread.
> It would need to:
> 1) be completely backwards compatible
> 2) not require additional unpythonic behavior (such as interfaces)
> 3) Existing models should be pluggable with no modification
> 4) Not require any significant change in code base

For the record, I'm not necessarily convinced that (3) is required --
I have no problem with the idea that a feature like plugability should
be opt in -- i.e., an application that wants to have a pluggable User
model needs to actively expose the User model as a point of
configuration. I'm not convinced that completely duck-typed User
replacement (or any other model, for that matter) is desirable,
because it can have all sorts of consequences.

Consider the simple task of bug reporting -- you report a bug with my
application, but I can't reproduce it. It's not until I really dig
into the matter and *then* I discover that you've been swapping out
the User model with a custom model that doesn't meet some requirement
that I may not have even known I was relying on.

It's also worth noting that (4) is desirable, but not absolutely
required. If it's necessary to tear down everything to get a better
implementation, we'll do that -- it's just not the preferred approach
due to the risks involved.

> 4) is the only part I cannot answer fully. I started an implementation, just
> to see if it was even possible,  and I've made some progress - it works with
> quite a few of my test models. However, I am just learning the internals of
> Django, and there are still errors with my implementation. I wanted to put
> this to the list before going further.
> As far as I've gotten with actual implementation: When a project imports the
> original model (original.model), django.db.models.base.ModelBase.__new__
> checks to see if "original.model." is in the COMPONENTS dictionary. If it
> is, it gets the path to the replacement model ("replacement.model2"), and
> gets the replacement class. It calls
> django.db.models.register_models('original', model=<class "model2">) which
> registers the replacement model class under the original application and
> with the name 'model'. Now, there are multiple copies of replacement.model2
> in django.db.models.loading.cache, so django.db.models.get_models() removes
> duplicates before returning all models. There are other internals that will
> need to be modified, besides these three methods, in order to eliminate the
> occasional errors I'm getting in syncdb; I'm still figuring out what those
> are.

Django has been down this path before... and came all the way back.
Our "magic removal" period was the point at which we finally purged
all the import shenanigans from our codebase, and I'm not eager to
revisit those dark times.

In short, messing with imports like this opens up a bag of hurt -- not
the least of which is a series of almost impossible to track down bugs
where the order in which models are imported can affect which model is
*actually* at the end of the rainbow when you say "from
django.contrib.auth.models import User". Even really simple things
like subclassing models can stops working... or worse... work
sometimes, but not always.

So - pluggable models -- yes. Getting pluggable models by messing with
the import/metaclass process -- no thanks.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to