#23694 closed Bug (wontfix)
Swappable Dependency should not use "__first__"
Reported by: | no | Owned by: | nobody |
---|---|---|---|
Component: | Migrations | Version: | 1.7 |
Severity: | Normal | Keywords: | |
Cc: | github@…, Andrew Godwin, Shai Berger | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Along the same vein as the other bugs I've recently reported about changing a model's db_table
option, it seems that changing it for AUTH_USER_MODEL
breaks any henceforth migrations that will depend on it.
To reproduce, try something a long the following:
- Start a new project and app with a customer
AUTH_USER_MODEL
, sayEmployee
- Set the
db_table
ofEmployee
to something, 'store_employee' - Create another model in another app
djbug
djbug/settings.py -> AUTH_USER_MODEL = 'app.Employee'
/app1/models.py
# /app1/models.py class Employee(models.Model): class Meta: db_table = 'store_employee' # /app2/models.py class Store(models.Model): pass
- Create and run migrations.
- Change the
db_table
ofEmployee
to the default, 'app_employee'. - Create an run the migrations with something like
migrations.AlterModelTable('Employee', 'accounts_employee')
- Add a many to many pointing to Employee
# /app2/models.py class Store(models.Model): employees = models.ManyTomanyField(settings.AUTH_USER_MODEL)
- Create a new migration.
The migration generated will include the migrations.swappable_dependency(settings.AUTH_USER_MODEL)
dependency, which expands to ('app1.Employee', '__first__')
. The problem with this, is that at __first__
, the db_table
option is pointing to a now non-existent table.
I propose that migrations.swappable_dependency
instead use either __latest__
, or find out what the current migration is for the application containing the AUTH_USER_MODEL
.
Change History (4)
comment:1 by , 10 years ago
Cc: | added |
---|
comment:2 by , 10 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Unfortunately, if it's set to __latest__
you get way more circular dependencies incredibly easily and other nasty categories of bugs - it's actually impossible to have a fixed dependency choice for custom user models that works, as changing the setting can dynamically change the model set without any detectable change by Django when it next runs.
This limitation (needing to have custom user models in the first migration) is documented: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model
While I'd love to know a way round it, __latest__
won't work, and "finding the migration containing the user model" is possible but nasty to implement. By enforcing this way we at least guarantee a lot less circular dependency errors later by giving you an error up front if it's wrong.
comment:4 by , 19 months ago
Cc: | added |
---|
Quoting myself from the duplicate ticket:
Another solution may be to load the app's migrations and look for a suitable
CreateModel
operation. That is not ideal, because models can be created by other operations (obviously the built-inRenameModel
, but even anAddField
with a M2M, not to mention 3rd-party operations).
A different approach would be just to check -- when a swappable dependency is in place, after running the initial migration of the dependency app, verify that the requested model exists, and if it doesn't, error out. That may later be extended, by allowing a specific migration to be marked (explicitly, in its code) as providing a specific model, but that extension may well be a YAGNI.
The above may justify reopening the ticket, as I believe it provides a partial answer to Andrew's comment:2 asking for a way around the limitations.
I know there was some things that used
__latest__
, but were later switched to use__first__
due to issues. Adding Andrew to comment.