On 04/04/2012, at 4:34 AM, Adrian Holovaty wrote:

> On Tue, Apr 3, 2012 at 9:28 AM, Alex Ogier <alex.og...@gmail.com> wrote:
>> I have written up a little bit about the alternate proposal that I made a
>> while ago, Solution 2a
>> from https://code.djangoproject.com/wiki/ContribAuthImprovements
> 
> ...
> 4. Third-party models should be changed to use something like "user =
> UserField()", which would automatically create a foreign key to the
> registered User model. If you change your registered User model after
> you've created those third-party tables, you're in for trouble. Don't
> do that.
> 

My only concern about this approach is making a special case of swappable 
Users. There's at least one other example of a swappable model in Django's core 
-- the Comments model -- and I have no doubt that we could find other examples 
with a quick survey.

If we're going down the path of swappable models, I'd rather set up the 
infrastructure to solve the *general* problem of swappable models, rather than 
just swappable *user* models specifically. 

If this required a massive increase in the effort required, I can see how 
practicality would determine that we just solve the immediate problem. However, 
in this case, it's really just a matter of avoiding User-specific naming on 4 
features:

 a) Specifying the model that can be swapped. 

This is just the name of the setting. USER_MODEL is fine by itself, and has 
obvious analogs with other models. However, an alternate way of spelling the 
same thing would be to have a single setting for all swappable models:

SWAPPABLE_MODELS = {
    'user': 'myauth.SuperDuperUser',
    'comment': 'comments.Comment',
}

in which you can define any extensible model, and provide a convenient key 
(e.g., 'user') to identify the value for that model.

 b) Preventing the "default" model from being added to the app cache, or 
synchronized to the database

contrib.auth is going to need ship with a User model, but we really don't want 
an auth_user table to be created, or get_model(auth,'User') to resolve, if the 
default User isn't being used. Same goes for any other swappable model.

Rather than make a special case of User inside syncdb, or nesting model 
definitions in if blocks, lets add a "swappable" attribute to Meta. If 
swappable is defined, syncdb checks the contents of SWAPPABLE_MODELS to see if 
this model has been substituted; if it has, then the table isn't created, and 
the model isn't added to the app cache. The value of pluggable can match the 
key in SWAPPABLE_MODELS (so auth.User would define swappable='user', following 
the previous example)

This can also act as a safety mechanism; if a developer has an app that 
contains a ForeignKey(User), and the User model has been swapped out, this can 
now raise a validation warning (notifying the developer that the User model 
could potentially be swapped out) or error (in the case where the model *has* 
been swapped out).

 c) Providing a way to specify foreign keys to that model

Rather than introduce a User-specific UserField(), introduce a generic 
LazyForeignKey('user') - both of which are effectively just 
ForeignKey(settings.XXXX) anyway.

 d) Provide a way to discover the current user model

Rather than have auth.get_user_model(), leverage the existing app cache. We 
already have get_model(); it wouldn't be too hard to add a 
get_swappable_model('user'). 

> 6. Given that some third-party apps will likely want to get access to
> common attributes of a User -- notably, email address -- there could
> be some sort of standard interface that User models need to adhere to
> (duck typing). So, a custom User model would say "for this User model,
> the email address is stored in the database field called 'email'" --
> or "this User model doesn't have email addresses."
> 

As I've noted elsewhere, this can be both a documentation issue, and backed up 
by an integration test. As a longer term goal, if someone ever takes the bait 
and does the Validation refactor for the GSoC (hint hint), it could also be 
extracted as a validation condition for an app.

Yours,
Russ Magee %-)


-- 
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