Hi, On Sun, Mar 18, 2012 at 9:41 AM, Russell Keith-Magee <russ...@keith-magee.com> wrote: >> 1. Django shouldn't decide what fields go on the user model. The app >> provides an abstract base class which developers subclass to add the >> appropriate fields they need. > > +1
THX >> 2. Django shouldn't decide the type of the primary key. The app only >> relies on the fact that the object has a pk. The id field can be named >> anything you wish and can be any type (integer, char, uuid, etc.). > > +1 THX again >> 3. Third party apps don't rely on the user having any fields but >> rather the base user class defines methods that are implemented by >> subclasses. Methods like get_display_name() which provides a way for >> third party apps to get something to display. >> 4. Rather than provide mixins or something, we should have conventions >> for the field names like 'email' and third party apps should check if >> the user has one using duck typing e.g. hasattr(user, 'email'). An >> alternative could be to provide some kind of API for commonly used >> actions like emailing users. > > This is essentially all I was proposing when I spoke of an "admin User > contract"; that we define some basic "identity" functions that every User > object is expected to provide -- short name, long name, and so on. > > The admin case is a little more complicated because there is also a required > API for permissions and groups, but to my mind, these are different > contracts, and should be documented as such. My solution is simply authentication, authorization would need to be added on or in a separate app built on top of newauth. >> 5. Basic username (or email)/password authentication can be provided. >> The app has a base user class from which a basic abstract user with >> username/password is defined. This can implement setting passwords >> properly and provide forms etc. >> 6. Multiple user models can be defined (Like say for normal users and >> affiliate users or admin users). If one wants to create a project >> currently with a separate user model, none of the machinery in the >> auth app can be used. > > Sure you can -- you have a base User, and then subclasses to get AdminUser > and NormalUser -- both of which are effectively just another type of > UserProfile. I meant one that was a completely separate concrete base model. The current auth forces you to take along with you all the fields on the User model. >> You create users by creating your own app in your project and creating >> a User there: >> >> account/models.py >> >> from django.db import models >> >> from newauth.models import UserBase >> >> class User(BaseUser): >> full_name = models.CharField(u"Full Name", max_length=255) >> email = models.EmailField('Email Address') >> profile = models.TextField('Profile Bio', blank=True, null=True) >> avatar = models.ImageField('Avatar', upload_to='profileimg/', >> blank=True, null=True) >> >> def get_display_name(self): >> return self.full_name >> >> class Meta: >> db_table = 'my_user_table' >> verbose_name = u"Djangonaut" >> verbose_name_plural = u"Djangonaut" >> >> There are even docs and tests. > > How does this address the issue of reusable apps referencing User? Let's say > I write a comments app, and want an Author field. I need a ForeignKey to > "User". But I can't have a foreign key to BaseUser, because it's an abstract > class. How do I define my Comment model in such a way that it can reference a > generic "User"? > > It seems to me that the solution you're proposing requires the LazyFK and > app-refactor infrastructure I've described in order to be useful in the > general case (not that I'm complaining, mind -- just pointing out that our > two proposals are complementary :-). This is a bad example for showing how that works. I just wanted to illustrate how you would make your own User model. In the case where you want a foreign key to User you can import the default user model from newauth.models as User much like you do with the current django auth app. See: http://ianlewis.bitbucket.org/django-newauth/third_party.html >> This is going to be the biggest problem with my solution. There would >> probably have to be some kind of compatibility layer added to make >> existing apps work or to provide a simpler migration path. > > Isn't the compatibility layer just an implementation of the existing > auth.User class that extends from BaseUser? We're going to have to ship this > user class anyway, so that everything works out of the box; then if anyone > wants to define their own User class, they can. Perhaps. I think in reality it will be a bit more complicated though I haven't really thought about it. I didn't really consider authorization or backwards compatibility as a goal of the project when first writing it. >>> * It solves the immediate problem ... >>> >>> As I see it, the immediate problem is that developers want to be able to >>> modify the base requirements of auth.User. There may well be people who >>> want to completely change contrib.auth, but for the moment, the 90% case >>> can be solved by modifying max_length or setting unique=True on the email >>> field, and/or removing the username field. The rest of auth.User is fine, >>> at least for now. >> >> I agree this is the most immediate problem. If you could do this it >> would be ok though I have other issues with auth that prevent me from >> using it so even if I could modify the fields on auth.User I still >> won't use it. > > I'm not completely convinced that your proposal isn't just the "long term > refactor" of auth that I referred to. I've only had a quick look at your > code, but it seems to share a lot of similarities with oldauth. Yes, there > have been modifications to remove dependencies on certain attributes of User, > but from my quick check, I didn't see anything that we couldn't achieve > through a process of modification of the existing code (if we didn't have an > existing pret-a-porter implementation like yours) That's perhaps true. I suppose the primary key thing and being able to separate admin and regular users were the things I personally wanted the most. >> There isn't much you need on a user object besides a primary key and >> maybe a way to authenticate it. Everything else is profile so things >> like the name, email, etc. are all profile. I just don't really see >> the benefit of breaking all this up and requiring you to do multiple >> lookups in every view or make a middleware that goes and gets the >> profile object for you. It's terribly inconvenient. On top of that the >> difference between a user and a profile isn't really all that clear >> in a lot of apps. I think if you need or want this kind of topology >> you can create it yourself in your project. > > Yes, all that is strictly needed is a PK and a way to authenticate -- but in > practice, a user object isn't much use unless you can say "Hello <user>", so > I don't see why basic identity mechanisms shouldn't be part of the basic User > contract (not necessarily defined at a data level, just at a data access > level). Sure. That's kind of why I defined an method for getting how to display the user's name. I think that when you say "but in practice, a user object isn't much use unless you can say "Hello <user>"", you are really saying that the user isn't much without the profile data. It's a very short step from wanting to display the user's name to wanting to display his email or something else. > Personally, I don't have a problem with UserProfile as a pattern, especially > when it comes to per-app settings. However, the good news is that both > approaches are possible once the User model is configurable. We can describe > the approach of a generic User with UserProfile objects containing app > settings; and also document the fact that if you have performance (or > taste/convenience) concerns about the joins to a UserProfile object, you can > define a per-project User object that incorporates all the profile data you > want. Yes. That's what I thought as well. There isn't stopping you from using the user profile approach or even defining multiple profiles. Thanks for taking a look at it, Ian -- Ian http://www.ianlewis.org/ -- 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.