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.

Reply via email to