11 | | A number of solutions have been proposed. Here is a summary of the most viable candidates: |
| 11 | == Design == |
| 12 | |
| 13 | The end goal is to provide as a built-in feature of Django a User model that is an exact analog of the historical contrib.auth.User, but with email as the identifying field. |
| 14 | |
| 15 | There are two major design questions that need to be answered: |
| 16 | |
| 17 | === Code Location === |
| 18 | |
| 19 | The first question: where should this code live? |
| 20 | |
| 21 | ==== Option 1: A new contrib.auth.email_user app ==== |
| 22 | |
| 23 | What it says on the tin. We add a new contrib app to contain the new code. Users install this app and point at the model/forms it provides. |
| 24 | |
| 25 | **Advantages:** |
| 26 | |
| 27 | * Good separation of concerns. contrib.auth remains essentially unchanged, except for any refactoring of base classes needed to support the new app. Users who don't want EmailUser don't have to carry any extra load from model parsing, import or caching. |
| 28 | * Sets a good example for third-party apps wanting to provide their own pluggable apps for Users. |
| 29 | |
| 30 | **Disadvantages:** |
| 31 | |
| 32 | * Requires 2 settings to use the new model -- ``INSTALLED_APPS`` and ``AUTH_USER_MODEL``. The counterargument to this is that users are used to installing apps to get access to models. |
| 33 | |
| 34 | ==== Option 2: Include EmailUser in contrib.auth ==== |
| 35 | |
| 36 | This requires the interpretation of ``Meta: swappable`` as "don't make this model visible unless the this model is referred to". This wasn't the original intended interpretation of ``Meta: swappable``, but the implementation supports this usage. If swappable is used in this way, the model is still loaded, parsed, and put into AppCache, but it isn't synchronized to the database, and any attempt to issue a query or generate a FK to the model will raise an error. |
| 37 | |
| 38 | **Advantages:** |
| 39 | |
| 40 | * Single point of configuration -- the developer need only set ``AUTH_USER_MODEL``. |
| 41 | |
| 42 | **Disadvantages:** |
| 43 | |
| 44 | * Overhead. Regardless of whether you want to use EmailUser, it must be loaded, parsed, and put in app cache. |
| 45 | * Arguably sets a bad example. Rather than the historical "one app, one concern", it encourages developers to put all possible models into a single app, and use ``swappable`` to prevent loading of a models that aren't needed at runtime. |
| 46 | * Depending on exact implementation, may require logic in views, forms, admin etc to control which code is active, depending on the active User model. |
| 47 | |
| 48 | === Code structure === |
| 49 | |
| 50 | ==== Option 1: Simple Subclass ==== |
| 51 | |
| 52 | Just rewrite the User model, but substitute email for username. Essentially copy/paste User, editing as required. |
| 53 | |
| 54 | **Advantages:** |
| 55 | |
| 56 | * Easy to do, easy to understand the end product. |
| 57 | |
| 58 | **Disadvantages:** |
| 59 | |
| 60 | * No facility for reuse. |
| 61 | * Sets a bad example for other developers by doing copy-paste. |
| 62 | |
| 63 | ==== Option 2: MOAR abstract base classes! ==== |
| 64 | |
| 65 | (RKM - I'm being facetious with these titles. Feel free to edit with something more meaningful :-) |
| 66 | |
| 67 | == Implementations == |
| 68 | |
| 69 | A number of implementations have been provided, providing various combinations of the above design decisions. Here is a summary of the most viable candidates: |