Hi all.
I summarise the options with some of the issues raised, and I add my own
concern.
One option presented here is to have both models in d.c.auth. As pointed out by
Russell and others, this causes the problem on how to define the models such
that they are not installed if they are not being the AUTH_USER_MODEL. Assuming
that this problem could be solved, the user's procedure would be:
To use User (+ Permissions):
install django.contrib.auth
To use MailUser (+ Permissions):
install django.contrib.auth
set AUTH_USER_MODEL to MailUser
The second option presented here is to add a separate app (e.g. d.c.mailuser),
which would require some imports from django.contrib.auth (forms, views). The
user's procedure would be:
To use User (+ Permissions):
install django.contrib.auth
To use MailUser (+ Permissions):
install django.contrib.auth
install django.contrib.mailauth
set AUTH_USER_MODEL to MailUser
Is this correct or I'm missing something important here?
If correct, I think the second option is cleaner, even though there is the
issue to minimise the repetition of code for forms, views, which was pointed
out to be easier to solve than the problem of model installation.
What I want to emphasise here is that django.contrib.auth has to be installed
in the case the custom model (email or other) is subclassed from
PermissionsMixin.
This is something that I'm bringing because it seems odd that d.c.auth has to
be installed even if we want to use mailuser (or any user). Wouldn't be
possible to detach permissions to a new app, say django.contrib.perms, and
remove the step of installing d.c.auth? I mean, we are in authentication;
permissions are not related with authentication.
Even though I think this is because historically auth was the contrib for all
these, which is good, I don't see why it should still be since now there are
custom models: now there is a specific reason where I can see an advantage in
separating these things; we could have a third option:
Django's state is:
django.contrib.auth for the standard user shipped by Django
django.contrib.mail_auth for the mail user shipped by Django
django.contrib.perms for permissions
To use AnyUser (shipped or not shipped):
install app_for_anyuser
set AUTH_USER_MODEL to AnyUser
To use AnyUser + Permissions:
install app_for_user
install django.contrib.perms
set AUTH_USER_MODEL to AnyUser
The settings for a new project would have AUTH_USER_MODEL =
'django.contrib.auth.models.User' and would have a new installed app
"django.contrib.perms"
I think this is nice and clean because:
1. is explicit
2. is intuitive how to change the auth model just by looking at the settings
3. keeps the separation that Russell pointed out between installing an app and
setting the auth model
4. (not sure, don't know enough): "swappable" can be deprecated: we just use
the one set in AUTH_USER_MODEL (and install its app, naturally)
5. Django's shipped user is no longer "special"; it is just the default in the
settings.
I have to admit this can be more serious than I'm seeing, but from the code I
saw in auth, it does seem to make some sense. Naturally there are required
migrations that have to be applied and so on, so, I'm not sure this should
deserve a discussion on its own.
In conclusion, I think that the discussion we are having is very related with
the fact that the standard User model is defined on the same app as
Permissions. Because permissions are required for any User that uses Admin,
d.c.auth has to be installed. Thus, we need to avoid installing User if we want
another User (i.e. we have to swap it).
My claim is that If we detach permissions from auth, we no longer have to
install User in the first place (we just install permissions), which means we
can select the user (custom or shipped) by installing its app and selecting it
in AUTH_USER_MODEL. I think this deprecates swappable, and makes the whole
thing more explicit and flexible.
Dos this make any sense?
Meanwhile or not, I agree that having separate apps is a solution worth
pursuing.
Regards,
Jorge
On Sep 19, 2013, at 3:41 PM, Marc Tamlyn <[email protected]> wrote:
> The problem you've got here is how it knows to *not* install EmailUser. If
> it's a model defined in d.c.auth.models, it will get installed, irrespective
> of whether it is AUTH_USER_MODEL or not. This is where we have to special
> case the new model somehow so it is only installed if we are using it. This
> is far from straightforwards! By putting it in a separate app which is not
> installed by default, then we solve this issue trivially without more magic.
>
> On 19 Sep 2013 05:27, "Luke Sneeringer" <[email protected]> wrote:
> Bah, I should have planned my e-mailing better. Sorry for sending a third in
> such rapid succession.
>
> I just did some checking into my assumptions (quoted below) on this. It turns
> out that Django core already does some of what I suggest: in particular, it
> doesn't install the User model if django.contrib.auth is installed but
> another AUTH_USER_MODEL is invoked, based on a Meta option called "swappable"
> (see [here][1] and [here][2]).
>
> Am I misunderstanding? It seems like we are already pretty well down my
> proposed path.
>
> Best Regards,
> Luke
>
> [1]:
> https://github.com/django/django/blob/b2b763448f726ee952743596e9a34fcb154bdb12/django/contrib/auth/models.py#L406-L414
> [2]:
> https://github.com/django/django/blob/master/django/db/models/loading.py#L296
>
>
> On Sep 18, 2013, at 10:03 PM, Luke Sneeringer <[email protected]> wrote:
>
>> On Wednesday, September 18, 2013 6:39:13 PM UTC-6, Russell Keith-Magee wrote:
>>
>> On Thu, Sep 19, 2013 at 3:39 AM, Luke Sneeringer <[email protected]>
>> wrote:
>> I added the authtools approach to the wiki for completion, although I
>> believe it to be an inferior approach.
>>
>> One thing I dislike is having a separate app (e.g. d.c.auth_email) that has
>> to be installed separately. That feels pretty impure to me. I'm doing a
>> thought exercise about potential solutions, though, and not exactly coming
>> up aces.
>>
>> The best solution I can currently think of is to have User and EmailUser
>> which are both models that live in django.contrib.auth. Then, we would have
>> to add code to our model detection that says that *if* a model is a subclass
>> of AbstractBaseUser, include it if and only if it is the AUTH_USER_MODEL.
>>
>> I can't decide if that solution is better or worse than the disease. It
>> makes for a much more attractive set of steps to follow for people who want
>> to use it, though -- basically, just set AUTH_USER_MODEL to
>> 'auth.EmailUser', and done.
>>
>>
>> My opinion - it's worse than the disease.
>>
>> Option 1 involves a clean auth app that just contains a stub user, and a
>> clean extension app providing an alternative user. You install the extension
>> app, and say you want to use it.
>>
>> Option 2 makes a special case of *one particular* extension user, and makes
>> all the internals of models, forms, views, etc embedded inside an if
>> statement.
>>
>>
>> I think where I part from you is on the "one particular" aspect of the
>> discussion. I actually see the "option 2" approach as having very clean side
>> effects for some other use cases.
>>
>> Allow me to explain:
>> There is, as you have pointed out, a lot more to auth than just the User
>> model. There are forms and the like, which you mentioned, but there are also
>> other aspects: the permissions models and functionality, for instance.
>> Subclasses of AbstractBaseUser which also subclass PermissionsMixin still
>> get the permissions things out of the box, and that is a documented use case
>> in the official documentation.
>>
>> So, right now (if I understand correctly), if you install the auth app, you
>> get the Group and Permission models (and supporting code, natch), as well as
>> the User model. If you decide to set a different User model using
>> AUTH_USER_MODEL, but you keep auth installed for these other aspects (Group,
>> Permission, etc.) then Django installs an auth_user table that isn't used
>> (note to self: verify this).
>>
>> If you set AUTH_USER_MODEL to something other than auth.User, you are making
>> a statement that you do not want the stock model. This is true whether you
>> change it to the upcoming, included "EmailUser" model, or to something else
>> entirely.
>>
>> So, I don't think that option 2 "makes a special case of one particular
>> extension user". If anything, I assert it would do the opposite: it actually
>> performs the most expected behavior in all cases. If the plain User model is
>> the AUTH_USER_MODEL and d.c.auth is in INSTALLED APPS, then it is installed.
>> If you choose to use an included-in-core e-mail model and install d.c.auth,
>> you get that model and table instead of the current User model. And, if you
>> use your own, special custom User model, but install auth for the remaining
>> aspects, then you get your custom user model, and not either of the stock
>> ones.
>>
>> Basically, my understanding is that you start to get unclean and
>> counter-intuitive behavior when you want to install the auth app for
>> everything other than the User model (and forms, etc.), that this would
>> correct.
>>
>> Best Regards,
>> Luke
>>
>> P. S. To be clear, I am not trying in any way to be argumentative, and I am
>> happy to implement the separate app if that is what the core developers
>> decide on.
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Django developers" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/django-developers.
>> For more options, visit https://groups.google.com/groups/opt_out.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/django-developers.
> For more options, visit https://groups.google.com/groups/opt_out.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/django-developers.
> For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.