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-d...@googlegroups.com.To unsubscribe from this group, send email to django-develop...@googlegroups.com.For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Yeah, that is the basic idea. I think that permissions and associated
code should be moved from UserBase to live directly on auth.User or in
a mixin of their own (they are mostly orthogonal to authentication,
yes?) so that writing one's own base user is easier, but the
monkey-patch looks like it is implemented in a nice way. So long as
writing your own base is easy enough, the extra special-case metaclass
and field overriding isn't strictly necessary, and can wait until
explicitly overriding fields has proper support in core (something I
think will be generally useful).
-Alex Ogier
It looks OK, but there is one really big issue with your approach - database blowup.
You can easily choose mixins to compose your User model, but once it's done your database layout is fixed.
If you then decide to use different mixins - it would be impossible without very smart db schema migration tool.