Problem importing model into consumers.py

Hello everyone,
I am building a simple chat web app with Django Channels and daphne.
In my code I want to store sent messages in the database. For that I created a “Message” Model in my app. When I try to import that model into consumers.py I get the error:

RuntimeError: Model class myproject.apps.chat.models.Message doesn’t declare an explicit app_label and isn’t in an application in INSTALLED_APPS.

The strange thing is, that I can import the model just fine into views.py.

Here is my models.py

from django.db import models
from django.utils.timezone import now

class Message(models.Model):
    username = models.CharField('Name', max_length = 20)
    text = models.TextField('Text')
    datetime = models.DateTimeField("DateTime", default=now)
    def __str__(self):
        return self.username + ' ' + self.text

Here is the beginning of my consumers.py, the error comes already from line 2

from channels.generic.websocket import WebsocketConsumer
from .models import Message
import json

class chatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

Here is the beginning of my views.py

from django.shortcuts import render, redirect
from django.utils.crypto import get_random_string
from .models import Message

def index(request):

Here are my INSTALLED_APPS in settings.py

INSTALLED_APPS = [
    'daphne',
    'channels',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'homepage.apps.HomepageConfig',
    'chat.apps.ChatConfig',
]

I did change the folder structure and I will try do describe it here as best as I can:

myproject/
    media/
    myproject/
        apps/
            chat/
                __init__.py
                admin.py
                apps.py
                consumers.py
                models.py
                routing.py
                tests.py
                urls.py
                views.py
        asgi.py
        settings.py
        urls.py
        wsgi.py
    static/
    templates/
    db.sqlite3
    manage.py

Maybe someone can help and I am fine to give more information if needed.
Thanks in advance

Hey there.
What’s the content of the file myproject/myproject/apps/chat/apps.py?
It looks like you created a directory inside the myproject/myproject directory: apps, generally apps reside on the same level as myproject. In that case you’ll want to review a config inside the file referenced above.

Hi,
my apps.py looks like this:

from django.apps import AppConfig

class ChatConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'chat'

You mean it should look something like this:

myproject/
    apps/
        chat/
    manage.py
    ...

Is it possible to do it the way I currently have it, or should I change the folder structure like that?
Thanks for the quick reply

You can have the way you want it.
It’s just not as smooth as the default way of doing it.

You can change the ChatConfig class to look like this:

from django.apps import AppConfig

class ChatConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'apps.chat'  # <--- Here
    # name = 'my_project.apps.chat'  # <-- If that don't work try this

Explanation:
Django uses the name attribute to load your module, so it will need to know where that project lives.
The above solution works, but you’ll need to change this on every new app you create.
And also when you want to use that app on your code, it will have a long import path, like:

from my_project.apps.chat.models import Message

Another way of tackling this is to not change the apps.py but to tell python to look your apps directory for imports as well, this is the sys.path variable. So, one thing that is also common, you’ll see this in the cookiecutter django template, is to add a given path to that variable, on the manage.py file (that’s the main entrypoint for your django project).

# manage.py 
import os
import sys
from pathlib import Path

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")

    try:
        from django.core.management import execute_from_command_line
    except ImportError:
        # The above import may fail for some other reason. Ensure that the
        # issue is really that Django is missing to avoid masking other
        # exceptions on Python 2.
        try:
            import django
        except ImportError:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            )

        raise

    # This allows easy placement of apps within the interior
    # my_project/apps directory.
    current_path = Path(__file__).parent.resolve()
    sys.path.append(str(current_path / Path("myproject") / "apps"))

    execute_from_command_line(sys.argv)

With this change, you can import your apps, like:

from chat.models import Message

Let me know if you got any of the solutions working.

I tried doing the changes in apps.py but that didn’t work. I haven’t had time to do the changes in manage.py yet since I need to work now for a few hours. I will try that when I’m back home and let you know.
Thank you

1 Like

While it is possible to set your project up this way, I always recommend against doing that, because it raises unnecessary issues that need to be addressed.

I always recommend working with Django and not try to work around it. Do things the way that Django expects, and everything else tends to be easier.

So yes, I would recommend that you restructure your project to match the Django defaults.

1 Like

Ok, I’m back now.
I changed the folder structure to this:

myproject/
    apps/
        chat/
            ...
    media/
    static/
    templates/
    asgi.py
    db.sqlite3
    manage.py
    settings.py
    urls.py
    wsgi.py

Is that correct? I still get the same error.

No. There should not be an apps directory. Your individual apps can reside directly in your project directory. (That is the default that Django expects.)

Also, your settings, urls, wsgi files are typically placed in an inner directory of the same name as the project directory.

If you’re not sure of what I’m referring to, start the Django tutorial. Do only the first page where you use the startproject and startapp commands, and see how the directories are structured.

Thank you, that worked. Changing the folder structure to the Django default fixed the problem. I will mark the post, that said I should change the structure as the solution.
Thanks a lot guys!

1 Like