#24351 closed New feature (fixed)
RunPython/RunSQL operations in contrib migrations and multi-db routers.
| Reported by: | Loic Bistuer | Owned by: | nobody |
|---|---|---|---|
| Component: | Migrations | Version: | 1.8alpha1 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
By default the RunPython and RunSQL don't give much information to the multi-db router, and before #22583 the router wasn't even consulted.
In Django 1.7 multi-db users could avoid issues by not using those operations and avoiding any 3rd party app that uses them. But in Django 1.8 the contenttypes application adds a RunPython operation that will fail in many multi-db setups (see commit).
To fix the immediate issue we can leverage the feature added by #22583 and provide hints to the router:
RunPython(foo, bar, hints={'app_label': 'contenttypes'})
and/or
RunPython(foo, bar, hints={'affected_models': [ContentType]})
Another option would be to make allowed_to_migrate always provide allow_migrate with the app_label for the current migration.
Both options would be backwards incompatible in the same way (although the first one is constrained to people that use django.contrib.contenttypes) because they require routers to accept the app_label kwarg or the new **hints syntax (see release notes).
Note that #22583 already introduced a backward incompatibility (see release notes) so people already have to update their existing routers for 1.8.
The advantage of the second option is that it'll automatically work for RunPython and RunSQL operations from 3rd party apps.
Change History (13)
comment:1 by , 11 years ago
| Has patch: | set |
|---|
comment:2 by , 11 years ago
Looking at the PR, I'm not sure we really need the app label on every allow_migrate call. Do we? I'd rather go with hints and put app_label and model_name in there. Or at least make app_label an optional argument in which case we can use inspect.getcallargs() to check if the respective function allows for that argument.
comment:3 by , 11 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:4 by , 11 years ago
To summurize what I mentioned on IRC:
Every migration and operation have an app_label but not necessarily a model so I think it'd be unfortunate to make the former an optional keyword arg while the latter is a required positional arg.
app_label always make sense when routing migrations, even if only as a first pass, not having it readily available requires convoluted code, see without app_label vs with app_label.
Existing routers need to be updated for Django 1.8 to handle model == None, since any router that inspects model._meta will blow up, so now is a good opportunity to get the API right.
inspect.getcallargs won't work because we document calling allow_migrate directly.
comment:5 by , 11 years ago
I've reworked the patch to allow a deprecation cycle for the old signature using inspect; things are unsurprisingly easier when I'm not half-asleep.
Of course it's still debatable whether or not allow_migrate(self, db, app_label, model, **hints) is the right API (I believe it is). I've started working on a ML post but it needs more work to properly lay out context and pros and cons of alternatives, I'm running out of time for today so it may have to wait for this weekend.
comment:6 by , 11 years ago
comment:7 by , 11 years ago
| Type: | Uncategorized → New feature |
|---|
comment:8 by , 11 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:9 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
comment:11 by , 11 years ago
| Severity: | Release blocker → Normal |
|---|
Tentative PR https://github.com/django/django/pull/4152.