There have been various proposals about replacing the User class with
an abstract base class. Ian Lewis has a semi-workable version at
http://ianlewis.bitbucket.org/django-newauth/index.html but its
proposal met with resistance in part because there's not a great
migration path from existing apps. I recently attended a Boston-area
python meetup, and met James Sullivan and Max Thayer, two of the guys
behind www.matchbox.net. We came up with a similar solution to Ian's,
but with a better path away from the status quo. Here's our flavor of
the abstract base class, based on the needs we see in other threads.

Starting from a basic set of premises:

1. People want to rip out auth.User’s authentication strictures
(username, email, password)
2. People want to plug in fields via distribution of apps, not just in
one project-wide user table
3. People want to depend on auth.User, by foreign key mostly
4. For the foreseeable future, by default auth.User has to map to its
old DB table

Here’s the clear winner for me: Make auth.User a subclass of an
abstract base class. It seems no one minds the whole auth permissions
thing sticking around even if it goes unused (if it ain’t broke don’t
fix it), so leave all that on auth.User and move everything else to
auth.DefaultUser, which is a class with Meta.abstract = True. Have
auth.User inherit from DefaultUser by default, with a setting to
override that with your own class(es). Languages like Ruby do this
with mixins, we do it with
https://docs.djangoproject.com/en/dev/topics/db/models/#multiple-inheritance

There are definitely some cons:

1. Requiring classes and settings to be available at the time of
definition of auth.User means circular dependencies are a problem.
2. Multiple inheritance is wonky and confusing in python, and only a
hackish sort of standin for mixins.
3. In the absence of a way to override fields (something that might be
added later?), you can’t subclass DefaultUser hoping to change a
default field, you can only add fields or reimplement the whole thing.
Thankfully that would be much easier.

But still the benefits are pretty large:

1. No changes to existing applications.
2. The common case of adding fields to users is easier even than
profiles: subclass DefaultUser, add your stuff, change a setting. No
get_profile() or select_related mumbo-jumbo.
3. The second use-case of ripping out auth.User’s broken assumptions
is possible: rewrite DefaultUser in your project.
4. The third use-case of plugging app mixins into the User model is easy.
5. The migration path is easy. You can incrementally step away from
the default user model, and (assuming running your migration framework
on a django.contrib app doesn’t blow up somehow) you can take
advantage of migrations without requiring them.
6. When you change fields, you break only the stuff that depends on
them. If you remove the username field, then half the default forms
stop working, but there’s no reason for auth middleware to break, etc.

Anyways, asides for circular dependency edge cases I think the rest of
the downsides can be mitigated by good docs. What do you guys think?

-Alex Ogier

P.S. I hear you are accepting GSOC applications.

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

Reply via email to