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.