Opened 7 years ago
Closed 7 years ago
#29283 closed Bug (invalid)
Difference between 'apps.get_model' and 'import' in migration
Reported by: | bronvic | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.11 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
HTR:
I have a model UserProfile
which looks like this:
class UserProfile(VStandardModel): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, default=None) mail = models.TextField(null=True, default=None, unique=True)
And I want to make migration which will do two things:
- Change user field to
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=False)
- If user was
None
set a user with an email
So I wrote a migration:
from __future__ import unicode_literals from django.conf import settings from django.db import migrations, models from django.core.exceptions import ObjectDoesNotExist from django.contrib.auth import get_user_model import django.db.models.deletion def empty_users(apps, schema_editor): UserProfile = apps.get_model('main', 'UserProfile') model_user = get_user_model() for profile in UserProfile.objects.all().only('user', 'mail'): if profile.user is None: try: profile.user = model_user.objects.get(email=profile.mail) except model_user.DoesNotExist: try: profile.user = model_user.objects.create(email=profile.mail, is_active=False) except Exception as err: print(err) profile.save() class Migration(migrations.Migration): dependencies = [ ('main', '0066_auto_20180222_1954'), ] operations = [ migrations.RunPython(empty_users, reverse_code=migrations.RunPython.noop), migrations.AlterField( model_name='userprofile', name='user', field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), ), ]
And, as you see, I emphasized an error in except Exception as err:
. It is: Cannot assign "<User: >": "UserProfile.user" must be a "User" instance.
.
But if I change UserProfile = apps.get_model('main', 'UserProfile')
to from main.models import UserProfile
migration will pass.
Note:
See TracTickets
for help on using tickets.
Hello there,
Without going into all the details you can't mix migration defined models with application defined ones. When writing
RunPython
executors you must always use the providedapps.get_model
method to retrieve models. In your particular caseget_user_model()
is going to return an application defined model class and not a migration one; you should useapps.get_model(settings.AUTH_USER_MODEL)
instead.In there future please avoid using this ticket tracker as a support channel TicketClosingReasons/UseSupportChannels.