On Mar 31, 12:48 pm, Russell Keith-Magee <freakboy3...@gmail.com> wrote: > On Wed, Mar 31, 2010 at 4:35 PM, Flo <d3f3n...@bytegeist.org> wrote: > > > Here an updated, fresh summary: > > > Plan > > ------- > > > Add an abstraction layer to the auth.User class > > > Method > > --------- > > > An extra abstraction layer will be added for the User class in form of > > a BaseUser class. The BaseUser class will consist of : > > > * the whole permission stuff (user_permissions, > > get_group_permissions, get_all_permissions,....), > > * the the authentication stuff (is_anonymous and is_authenticated, > > last_login, date_joined, groups) > > * the fields for admin (is_staff, is_superuser) > > * a single ident field > > > The interface will look something like this: > > > class BaseUserPermission: -> abstract > > - user_permissions > > - groups > > - get_group_permissions() > > - get_all_permissions() > > - has_perm() > > - has_module_perms() > > - ….. > > > class BaseUserAuthentication: -> abstract > > - last_login > > - date_joined > > - is_anonymous() > > - is_authenticated() > > - ….. > > > class BaseUserAdmin: -> abstract > > - is_staff > > - is_superuser > > > class BaseUser(BaseUserAuthentication, BaseUserPermissions, > > models.Model): > > - ident > > - ….. > > I'm not entirely clear what we gain by having multiple base classes. > If every application that wants to reference User needs to have a > foreign key on BaseUser, then the base classes of BaseUser are > irrelevant. It's not like I could define my own User class that used a > different UserAuthentication or UserPermissions class. > >
There are only small benefits in seperating BaseUser in multiple classes, but I think there are some. I think seperating into multiple classes makes the code clearer and there is the possibility to add a way to use your own permission model to BaseUser, but I don't know what you think about this!? > > > All specific user classes (for example a class for login via a Twitter > > user) will have to extend BaseUser via Multi-Table inheritance. The > > new Django auth.User will have the same fields and methods as the old > > User, but it will inherit the fields and mehtods for permissions, > > authentication and admin. > > To add your custom user class for remote login via Twitter/ > > Facebook..... you will only have to extend base user and add the > > fields you need (no more linking to the old auth.User and having a lot > > of fields you don't need, username and password (because the login is > > handled via an external service) for example). The new existing Django > > user class can be modified via inheritance too (for example adding > > another permission model or additional authentication information). > > > While the new User class won't break code compatibility, because it > > will contain all the fields and methods the "old" User class does, it > > will break database compatibility, because the new User will consist > > of two or more database tables. Two ways of dealing with the new user > > class will be supported: > > Erm.. aren't these two approach mutually exclusive? i.e., if we force > a migration, we won't need NewUser at all. > Yes, if you force a migratio, we won't need NewUser, but my plan is provide a tool for migration, not forcing the user to use to new system immediately. > > Use the new system: > > A tool for migrating the database will be provided to support the > > transition from old to new. The script will work to following way: > > I have to say I'm *really* not a fan of this. Completely aside from > the complexities associated with dumping and recreating your entire > collection of user data, this is a nightmare waiting to happen from a > project management point of view. We aim to make Django point releases > "just upgrade and you'll be able to keep running". The defaults of any > new features are specifically designed to avoid update problems. > Putting a forced data migration as part of the upgrade path sounds > like a recipe for putting me in an early grave. > I know about the "just upgrade and you'll be able to keep running" philosophy behind Django. The timeline I posted was only one possible way to target the compatibility issue. In fact, the abstract layer can be introduced as purely additional, with no deprecation timeline, maybe as PluggableUser and only people who need the behavior of a pluggable user. The "old" user may be removed in another major release (2.0), if most new apps use the pluggable system. > > Don't use it: > > The new User class will be introduced as auth.NewUser and the old > > User class won't be touched, so all apps, that rely on the old User > > will work as well. Of course, the Django internals have to modified to > > work with both User systems, the "old" and the "new" one. > > That last sentence is a fairly big thing to gloss over. How exactly > will this magical parallel support be implemented? What changes are > required in core to utilize this parallel support? Are they the same > changes that external applications will need to make? > I had a deeper look into some django internals that rely on User (messages, admin and of course auth). I will list some cases I discovered: * linking to User: example: django.contrib.admin.models.LogEntry solution: if USE_ABSTRACT_USER: from django.contrib.auth.models import BaseUser as User else: from django.contrib.auth.models import User * accessing permission/authentication methods of the request.user object (most used) examples: * django.contrib.admin.models.views.decorators.staff_member_required * django.core.xheaders.populate_xheader * django.middleware.cache * and many more solution: the request.user object (BaseUser class) will have the same fields/methods for permissions and authentication as the "old" auth.User, so no problem * accessing other fields/methods of request.user used in: * django/contrib/comments/views/comments.post_comment (get_full_name(), username, email), used to fill out some initial data fields from request.user solution: only works with the Django User class (which supports username and email) so check if request.user is an instance of auth.User or auth.NewUser, if not, don't fill out the fields (maybe use indent instead of username, to use a field from BaseUser * getting user objects example: django.contrib.auth.backends.ModelBackend solution: same as when linking to User solution: if USE_ABSTRACT_USER: from django.contrib.auth.models import BaseUser as User else: from django.contrib.auth.models import User I think and hope I've covered most of possible cases and so far I don't see any unsolvable problems. > > In the long term NewUser will replace the current auth.User. The > > deprecation plan will look like: > > > * 1.3 > > The new system can be activated via USE_ABSTRACT_USER=True in > > settings (default False). Inside your app, the new User class will be > > imported as : "from django.contrib.auth.models import NewUser as User" > > The use of the old User will raise a PendingDeprecationWarning > > > * 1.4 > > raise a DeprecationWarning, if the old auth.User is used > > > * 2.0 > > NewUser will become User, support for old User will be dropped > > Again - a kind of big detail to gloss over... the release after 1.4 > won't necessarily (in fact, almost certainly won't be) be 2.0. How > long do you expect us to maintain parallel support? > > > Benefits > > ------------ > > > * Apps can link pages, posts,..... to BaseUser and become > > independent from the underlying user class -> underlying user classes > > are exchangeable -> apps are more portable > > * User classes for remote authentication without unused fields (like > > password, username...) > > * clear, object oriented User classes > > This last point might sound great to a Java developer, but arguing > OO=better won't necessarily win you the hearts and minds of Python > developers. Don't get me wrong - OO is useful and has its place. > However, it isn't always a guaranteed win. For example, there is a > very significant cost to your OO proposal that you have consistently > overlooked - the fact that using OO requires an additional table join. > This join doesn't come for free, and I'm not yet convinced that it > actually improves flexibility to force the extra join on everyone. > I don't say OO is better in general ( and I don't like languages that force you to use OO), but I think I've highlighted some benefits of the OO User layer. I'm aware of the extra join (and the impact of the performance of the app), but every solution for remote login (via facebook, twitter and so on) I know uses an extra join to auth.User. Everything comes with a price of course, so people who need the plain Django User without the benefits of the new system can keep on using the "old" auth.User. People who want to add custom information to User or use a remote service for authentication are aware of the extra join. I think it would be a good idea to let the user choose what's more important for their app! Yours Flo -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@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.