Are we really sure that we can or should stomach a swappable User model as a special case?
It's highly likely that I am missing something (or a few things), but aren't the main benefits of swapping the User model just to avoid making a backwards incompatible change, and to avoid making `select_related()` queries? I'm not suggesting that backwards incompatibility is not important, but I'm not convinced by the argument about inefficient `select_related()` queries, and whatever we do will involve manual schema migration for many users. Do we really need to allow users to swap in their own model with a combination of additional project level fields as well as additional fields required by various pluggable apps as the primary `User` model, instead of simply stripping out authentication and identifying fields from the primary `User` model and allowing users to implement whatever they need as app or project level profile models? The more I think about it, the more I think this will just lead to more fragmentation and incompatibilities with pluggable apps, when the user "interface" is abused or causes conflicts. What's going to happen when this is rolled out and people start developing an eco-system of pluggable apps without a concrete `User` model in Django? All they can rely on is that there will be some form of `User` model and that it *should* provide at least a minimal set of fields and behaviours as specified by some guidelines in Django docs? Won't we just be back at square 1 in deciding what to include in the minimal fields and guidelines for the this "contract"? Isn't the only sensible minimal set of fields, no fields at all? Pluggable apps will have to either dictate to developers in the installation instructions that their particular `User` model must have certain fields or behaviours that are required by the pluggable app, which may even conflict with other pluggable apps. Or they will still have to fallback to using an app-profile model, which brings us back to using `select_related()` anyway. I don't like the idea that a pluggable app might require users to change their existing models like this. If pluggable apps will still need to use app-profile models anyway, if we can get past the backwards incompatibility issue, what is so bad about simply having a `User` model which has no auth or identity data in it, but is just there as glue for for apps to share data for a single "user"? Bundled apps like the admin would define `AdminProfile` and any pluggable apps that require or support the admin could access `user.admin_profile`. Pluggable apps that don't use the admin and/or have their own auth or identifying requirements can just ship with their own profile and/or auth models and optional auth backend. The only real issue I have with Django users/auth as it is right now is that there are redundant (for me) or non-compliant (with RFC) fields in `auth.User` that are required and that I have to fake in order to hook into the admin, groups and permissions or re-specify in my own profile for RFC-compliance. The other problem I have seen mentioned with the profile approach is managing common fields (e.g. two pluggable apps that have a "name" field). I'm quite happy for this to be managed by the developer at a project level, either using signals or forms or a `save()` method on their profile model or whatever else they like to keep that data in sync, if it needs to be kept in sync. I don't think pluggable apps requiring that developers have a "name" (for example) field on their primary `User` model is really a good solution to this problem, because the pluggable app doesn't know what other purpose that field is used for, and doesn't know if it is changed in app1 if it will have any consequences for app2. If developers really want a single project level `User` model, they can still create that (with an FK back to Django's `User` model), and simply update it's `save()` method to sync any common fields on all the pluggable app's profile models (which may even have different field names). E.g. `project.User` could have `first_name` and `last_name`, but app1 has only `name`, and app2 has `given_name` and `family_name`. In `project.User.save()`, the developer of a project can determine how to sync this data. Cheers. Tai. On Thursday, 5 April 2012 00:57:57 UTC+10, Jacob Kaplan-Moss wrote: > > On Wednesday, April 4, 2012 at 9:44 AM, Russell Keith-Magee wrote: > > My point is that there is nothing about this problem that is unique to > User. Django's own codebase contains another example of exactly the same > pattern -- Comments. > > As the original author and designer of that pattern, I should probably > point out that I now think it's a mistake. Have you actually tried using > it? It doesn't really work very well. Every time I've introduced any sort > of "swappable model" mechanism I've come to regret it. > > I'm -1 on the idea of generalized "swappable model" mechanism. I can > stomach it for User because in this context it's not any worse than the > alternatives, but as a generalized mechanism it makes me really, really > unhappy. Decoupling is a laudable goal, but providing a mechanism to reach > in and effect code not under your control isn't good design. We use > derisive terms like "monkeypatching" for a reason. > > I'm sure there are good reasons for wanting swappable models. Russ, I know > you're smarter than me, so the fact that you want LazyForeignKey so much > probably indicates that you've got some really solid use cases in mind. But > really this is a hard veto from me; I just can't be convinced that this > sort of mechanism is anything but bad news. > > However, I don't see why we should actively prevent this sort of thing > being done externally, so if there's anything in Django that's precluding > the creation of a LazyForeignKey as an external add-on let's consider that > limitation a bug and get it fixed. > > Jacob > On Thursday, 5 April 2012 00:57:57 UTC+10, Jacob Kaplan-Moss wrote: > > On Wednesday, April 4, 2012 at 9:44 AM, Russell Keith-Magee wrote: > > My point is that there is nothing about this problem that is unique to > User. Django's own codebase contains another example of exactly the same > pattern -- Comments. > > As the original author and designer of that pattern, I should probably > point out that I now think it's a mistake. Have you actually tried using > it? It doesn't really work very well. Every time I've introduced any sort > of "swappable model" mechanism I've come to regret it. > > I'm -1 on the idea of generalized "swappable model" mechanism. I can > stomach it for User because in this context it's not any worse than the > alternatives, but as a generalized mechanism it makes me really, really > unhappy. Decoupling is a laudable goal, but providing a mechanism to reach > in and effect code not under your control isn't good design. We use > derisive terms like "monkeypatching" for a reason. > > I'm sure there are good reasons for wanting swappable models. Russ, I know > you're smarter than me, so the fact that you want LazyForeignKey so much > probably indicates that you've got some really solid use cases in mind. But > really this is a hard veto from me; I just can't be convinced that this > sort of mechanism is anything but bad news. > > However, I don't see why we should actively prevent this sort of thing > being done externally, so if there's anything in Django that's precluding > the creation of a LazyForeignKey as an external add-on let's consider that > limitation a bug and get it fixed. > > Jacob > -- You received this message because you are subscribed to the Google Groups "Django developers" group. To view this discussion on the web visit https://groups.google.com/d/msg/django-developers/-/p2gpf3R9evsJ. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
