1

Stumbled upon something very weird today.

I created a minimal project/application that can show the issue. This is how I did it:

virtualenv venv
. ./ven/bin/activate
pip install django==1.6 # That's the one we're using
django-admin.py startproject bla
cd bla
chmod +x manage.py
./manage.py startapp bla_app

in bla/settings.py:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'bla_app',
)

AUTH_USER_MODEL = 'bla_app.MyUser'

in bla_app/models.py:

from django.db import models

from django.contrib.auth.models import AbstractUser

# Create your models here.


class MyUser(AbstractUser):
    super_name = models.CharField(max_length=254, unique=True)

Then, I run the syncdb command:

./manage.py syncdb

And it's been created as expected.

Now comes the tricky part. If I replace the models.py with a folder called models, and create an __init__.py file containing:

from my_user import MyUser

(the previous models.py was moved into models/ as my_user.py)

I then get these errors:

$ ./manage.py syncdb
CommandError: One or more models did not validate:
admin.logentry: 'user' has a relation with model bla_app.MyUser, which has either not been installed or is abstract.
auth.user: Model has been swapped out for 'bla_app.MyUser' which has not been installed or is abstract.

Do you have an idea of what is going on here?

I found that, but I'm not sure they're related

Paco
  • 4,520
  • 3
  • 29
  • 53
  • Partitioning of models to submodules is not supported (only for models) becuase of the way django works, this will change in 1.7: https://code.djangoproject.com/ticket/4470 Check at the end for a "trick" on how to perform that. – petkostas Aug 11 '14 at 17:22

2 Answers2

2

Django expects your model classes to be defined in models.py itself, not in a submodule. It's going to try to create an instance of models.MyUser which in your case does not exist in Django's world even though you've defined it in my_user.py

If you're looking to define each model in a separate Python file, you'd need to create a models.py file that imports them manually. This will likely be hard to maintain if you start creating a lot of models in that app.

app/
    __init__.py
    models.py
    _models/
        __init__.py
        my_user.py

In models.py

from ._models.my_user import MyUser
asoc
  • 116
  • 3
  • I am pretty sure it would work, but I still prefer the `app_label` in the `Meta` class as @renan-ivo suggested. – Paco Aug 12 '14 at 09:25
1

To split your model into modules, you have to provide the app_label Meta Option. Ex:

my_user.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class MyUser(AbstractUser):
    super_name = models.CharField(max_length=254, unique=True)
    class Meta:
        app_label = 'bla_app'

As @petkostas said, it will not be required in Django 1.7 (issue 4470)

Take a look at this answer, which describes the process.

Community
  • 1
  • 1
Renan Ivo
  • 1,368
  • 9
  • 17
  • Thanks, that does it. It is just a pain to remember that if we rename the app for some reason, we need to edit *all* the app_label values. But that will do for now. – Paco Aug 12 '14 at 09:27