Search code examples
pythondjangoupgradedjango-1.9

ValueError when upgrading from Django 1.8 to 1.9


I have recently upgraded a project to 1.9 from 1.8.11, Everything worked fine on 1.8 and I have worked through the deprecation warnings and cleaned a lot of things up within the project.

When I try to run the project I get an error

ValueError: Cannot create form field for 'country' yet, because its related model 'Country' has not been
loaded yet

I have been trying to figure this out for a few hours now and would really appreciate some help

I have looked through the upgrading instruction on the Django website, upgraded some dependencies which fixed one or two warnings but still not fixed the Issue.

User = settings.AUTH_USER_MODEL
class Country(TimeStampedModel):
    name = models.CharField(max_length=50, unique=True)
    code = models.CharField(max_length=2, null=True, blank=True, db_index=True)
    code3 = models.CharField(max_length=3, null=True, blank=True, unique=True)
    last_updated_by = models.ForeignKey(User, null=True, blank=True, related_name='%(class)s_last_updated_by')
    created_by = models.ForeignKey(User, default=settings.SYSTEM_USER_ID, related_name='%(class)s_created_by')

    objects = models.Manager()
    countries = CountryManager()

    class Meta:
        verbose_name = _('country')
        verbose_name_plural = _('countries')
        ordering = ['name']

    def __str__(self):
        return self.name

class AddressAbstractModel(TimeStampedModel):
    country = models.ForeignKey('Country', verbose_name=_('country'), null=True, blank=True)
    address_1 = models.CharField(_('street address line 1'), max_length=50, blank=True)
    address_2 = models.CharField(_('street address line 2'), max_length=50, blank=True)
    city = models.CharField(_('city'), max_length=50, blank=True)
    postal_code = models.CharField(_('postal code'), max_length=20, blank=True)
    latitude = models.DecimalField(_('Latitude'), max_digits=9, decimal_places=6, null=True, blank=True)
    longitude = models.DecimalField(_('Longitude'), max_digits=9, decimal_places=6, null=True, blank=True)

    class Meta:
        abstract = True

Forms


User = get_user_model()

class UserChangeForm(forms.UserChangeForm):
    class Meta:
        model = User
        fields = '__all__'
        help_texts = {
            'username': _('Required. Letters, digits and @/./+/-/_ only.')
        }


class UserCreationForm(forms.UserCreationForm):
    class Meta:
        model = User
        fields = ("username",)
        help_texts = {
            'username': _('Required. Letters, digits and @/./+/-/_ only.')
        }

EDIT: requested full traceback

web_1_1b9067fcd9a4 | Traceback (most recent call last):
web_1_1b9067fcd9a4 |   File "manage.py", line 10, in <module>
web_1_1b9067fcd9a4 |     execute_from_command_line(sys.argv)
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/core/management/__init__.py", line 350, in execute_
from_command_line
web_1_1b9067fcd9a4 |     utility.execute()
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/core/management/__init__.py", line 324, in execute
web_1_1b9067fcd9a4 |     django.setup()
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/__init__.py", line 18, in setup
web_1_1b9067fcd9a4 |     apps.populate(settings.INSTALLED_APPS)
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/apps/registry.py", line 115, in populate
web_1_1b9067fcd9a4 |     app_config.ready()
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/contrib/admin/apps.py", line 22, in ready
web_1_1b9067fcd9a4 |     self.module.autodiscover()
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/contrib/admin/__init__.py", line 26, in autodiscove
r
web_1_1b9067fcd9a4 |     autodiscover_modules('admin', register_to=site)
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/utils/module_loading.py", line 50, in autodiscover_
modules
web_1_1b9067fcd9a4 |     import_module('%s.%s' % (app_config.name, module_to_search))
web_1_1b9067fcd9a4 |   File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module
web_1_1b9067fcd9a4 |     return _bootstrap._gcd_import(name[level:], package, level)
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap>", line 994, in _gcd_import
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap>", line 971, in _find_and_load
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap_external>", line 678, in exec_module
web_1_1b9067fcd9a4 |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
web_1_1b9067fcd9a4 |   File "winda/users/admin.py", line 11, in <module>
web_1_1b9067fcd9a4 |     from .forms import UserChangeForm, UserCreationForm
web_1_1b9067fcd9a4 |   File "winda/users/forms.py", line 5, in <module>
web_1_1b9067fcd9a4 |     class UserChangeForm(forms.UserChangeForm):
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/forms/models.py", line 247, in __new__
web_1_1b9067fcd9a4 |     opts.field_classes)
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/forms/models.py", line 172, in fields_for_model
web_1_1b9067fcd9a4 |     formfield = f.formfield(**kwargs)
web_1_1b9067fcd9a4 |   File "/usr/local/lib/python3.6/dist-packages/django/db/models/fields/related.py", line 937, in formfiel
d
web_1_1b9067fcd9a4 |     (self.name, self.remote_field.model))
web_1_1b9067fcd9a4 | ValueError: Cannot create form field for 'country' yet, because its related model 'Country' has not been
loaded yet

Installed apps

DJANGO_APPS = (
    # Default Django apps:
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Useful template tags:
    # 'django.contrib.humanize',

    # Admin
    'django.contrib.admin',
    'django.contrib.flatpages',
)
THIRD_PARTY_APPS = (
    'widget_tweaks',
    'storages',
    'reversion',
    'django_ses',
    'timezone_field',
    'ckeditor',
    'ckeditor_uploader',
    'rest_framework',
    'rest_framework.authtoken',
    'solo',
    'phonenumber_field',
    'allauth',
)

# Apps specific for this project go here.
LOCAL_APPS = (
    # Your stuff: custom apps go here
    'core',
    'users',
    'common',
    'registration',
    'trainings',
    'courses',
    'delegate',
    'organization',
    'database_admin',
    'database_super_admin',
    'orders',
    'api',
)

user Modal

class User(AbstractBaseUser, PermissionsMixin, UserProfileAbstract):

    UNKNOWN, BOUNCE, COMPLAINT, DELIVERY = 'Unknown', 'Bounce', 'Complaint', 'Delivery'

    EMAIL_STATUS_CHOICE = (
        (UNKNOWN, 'Unknown'),
        (BOUNCE, 'Bounce'),
        (COMPLAINT, 'Complaint'),
        (DELIVERY, 'Delivery')
    )

    delegate_id = models.CharField(_('delegate id'), unique=True, max_length=12, null=True, default=None, db_index=True)
    expires_at = models.DateTimeField(_('expires at'), default=TimeStampedModel.user_expires_at_default)
    email_status = models.CharField(_('email status'), max_length=10, choices=EMAIL_STATUS_CHOICE)
    role = models.CharField(_('role'), max_length=30, choices=UserProfileAbstract.ROLE_CHOICE, db_index=True)
    company_name = models.CharField(_('company name'), max_length=50, blank=True)
    last_updated_by = models.ForeignKey('self', default=settings.SYSTEM_USER_ID, null=True, related_name='%(class)s_last_updated_by')
    created_by = models.ForeignKey('self', default=settings.SYSTEM_USER_ID, null=True, related_name='%(class)s_created_by')
    archived_by = models.ForeignKey('self', null=True, related_name='%(class)s_archived_by', blank=True)
    can_upload = models.BooleanField(_('can upload files'), default=False)
    can_buy_credit = models.BooleanField(_('can buy credits'), default=False)
    can_use_credit = models.BooleanField(_('can use credits'), default=False)
    can_ask_revoke = models.BooleanField(_('can ask to request certificate revokes'), default=False)
    is_tp_site_access = models.BooleanField(_('Access to all TP site profiles'), default=False)
    api_rate_limit = models.IntegerField(_('daily API request limit'), default=settings.API_CALL_RATE_LIMIT, blank=True)
    is_api_enabled = models.BooleanField(_('API enabled'), default=False, blank=True)

    username = models.CharField(_('username'), max_length=255, unique=True,
        help_text=_('Required. 255 characters or fewer. Letters, digits and '
                    '@/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(r'^[\w.@+-]+$',
                                      _('Enter a valid username. '
                                        'This value may contain only letters, numbers '
                                        'and @/./+/-/_ characters.'), 'invalid'),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        })
    first_name = models.CharField(_('first name(s)'), max_length=100, blank=False)
    last_name = models.CharField(_('surname'), max_length=100, blank=False)
    email = models.EmailField(_('email address'), blank=False, max_length=255)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = WindaUserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def __str__(self):
        return self.username


class UserProfileAbstract(AddressAbstractModel):


    archived_from = models.DateTimeField(_('archived from'), default=TimeStampedModel.archived_from_default)
    archived_at = models.DateTimeField(_('archived at'), null=True, blank=True)
    job_title = models.CharField(_('job title'), max_length=50, blank=True)
    organization_name = models.CharField(_('organisation name'), max_length=200, blank=True)
    training_provider = models.ForeignKey(TrainingProvider, verbose_name=_('training provider'), null=True, blank=True,
                                          related_name='%(class)s_users')
    phone = models.CharField(_('work phone number'), max_length=15, blank=True)
    timezone = TimeZoneField(default='Europe/London')

    class Meta:
        abstract = True

Solution

  • You've hit issue #25858. When AddressAbstractModel is used by the users.User model, 'Country' resolves to users.Country, which does not exist.

    You can fix the problem by using common.Country in the abstract model's foreign key.

    See the example in the foreign key docs for more information.