#29897: Initial migration fails when referencing a custom user model from a
sequence of at least two concrete ancestor models
-------------------------------------+-------------------------------------
               Reporter:             |          Owner:  nobody
  stevenganz                         |
                   Type:  Bug        |         Status:  new
              Component:             |        Version:  2.1
  Migrations                         |
               Severity:  Release    |       Keywords:  "custom user model"
  blocker                            |  "abstract model" "foreign key"
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 The following model fails on initial migration.
 {{{
 from django.db import models
 from django.contrib.auth.models import (AbstractBaseUser)

 class A(models.Model):
     createdByUser = models.ForeignKey('User', related_name='creations+',
 verbose_name='creatorUser', blank=True, null=True, editable=False,
 on_delete=models.PROTECT)

 class B(A):
     pass

 class User(AbstractBaseUser, B):
     email = models.EmailField('email address', max_length=256,
 unique=True, db_index=True)
     USERNAME_FIELD = 'email'

     @property
     def username(self):
          return self.email
 }}}

 settings.py contains:
 {{{
 AUTH_USER_MODEL = 'core.User'
 }}}

 {{{
   Applying core.0001_initial...Traceback (most recent call last):
   File "./manage.py", line 13, in <module>
     execute_from_command_line(sys.argv)
   File ".../lib/python3.6/site-
 packages/django/core/management/__init__.py", line 364, in
 execute_from_command_line
     utility.execute()
   File ".../lib/python3.6/site-
 packages/django/core/management/__init__.py", line 356, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File ".../lib/python3.6/site-packages/django/core/management/base.py",
 line 283, in run_from_argv
     self.execute(*args, **cmd_options)
   File ".../lib/python3.6/site-packages/django/core/management/base.py",
 line 330, in execute
     output = self.handle(*args, **options)
   File ".../lib/python3.6/site-
 packages/django/core/management/commands/migrate.py", line 204, in handle
     fake_initial=fake_initial,
   File ".../lib/python3.6/site-packages/django/db/migrations/executor.py",
 line 115, in migrate
     state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
 fake_initial=fake_initial)
   File ".../lib/python3.6/site-packages/django/db/migrations/executor.py",
 line 145, in _migrate_all_forwards
     state = self.apply_migration(state, migration, fake=fake,
 fake_initial=fake_initial)
   File ".../lib/python3.6/site-packages/django/db/migrations/executor.py",
 line 244, in apply_migration
     state = migration.apply(state, schema_editor)
   File ".../lib/python3.6/site-
 packages/django/db/migrations/migration.py", line 129, in apply
     operation.database_forwards(self.app_label, schema_editor, old_state,
 project_state)
   File ".../lib/python3.6/site-
 packages/django/db/migrations/operations/fields.py", line 88, in
 database_forwards
     field,
   File ".../lib/python3.6/site-
 packages/django/db/backends/base/schema.py", line 431, in add_field
     definition, params = self.column_sql(model, field,
 include_default=True)
   File ".../lib/python3.6/site-
 packages/django/db/backends/base/schema.py", line 160, in column_sql
     db_params = field.db_parameters(connection=self.connection)
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 994, in db_parameters
     return {"type": self.db_type(connection), "check":
 self.db_check(connection)}
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 991, in db_type
     return self.target_field.rel_db_type(connection=connection)
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 909, in target_field
     return self.foreign_related_fields[0]
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 653, in
 foreign_related_fields
     return tuple(rhs_field for lhs_field, rhs_field in self.related_fields
 if rhs_field)
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 640, in related_fields
     self._related_fields = self.resolve_related_fields()
   File ".../lib/python3.6/site-
 packages/django/db/models/fields/related.py", line 625, in
 resolve_related_fields
     raise ValueError('Related model %r cannot be resolved' %
 self.remote_field.model)
 ValueError: Related model 'core.User' cannot be resolved
 }}}

 Notably, this works fine with any of the following modifications:
 - model B is removed, closing the chain
 - createdByUser is moved to B or removed altogether
 - either A or B is made abstract
 - the referenced model is not the custom user model

 This is not just a matter of preference for concrete classes, as only a
 concrete class can be referenced through a foreign key.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29897>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/053.412383d00b357ad9280184efc998d268%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to