How to keep all my django applications in specific folder
Asked Answered
U

9

60

I have a Django project, let's say "project1". Typical folder structure for applications is:

/project1/
         /app1/
         /app2/
         ...
         __init__.py
         manage.py
         settings.py
         urls.py

What should I do if I want to hold all of my applications in some separate folder, 'apps' for example? So that structure should look like the following:

/project/
         apps/
              app1/
              app2/
              ...
         __init__.py
         manage.py
         settings.py
         urls.py
Unexpressive answered 16/10, 2010 at 9:42 Comment(0)
E
66

You can add your apps folder to your python path by inserting the following in your settings.py:

import os
import sys

PROJECT_ROOT = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))

Then you can use all the apps in this folder just in the same way as they were in your project root!

Eccrine answered 16/10, 2010 at 12:9 Comment(6)
If you ask me, this leads to confusion.Enalda
This leads to conflicts when running tests.Mountie
@ErnestJumbe What kind of conflicts when running tests? I use this methods and run tests fine.Horlacher
Does this work with Django 3? I get a ModuleNotFoundError: No module named 'pages' when I run the server. pages is the name of one of the apps.Doralynne
For Django 3 this answer worked: https://mcmap.net/q/325999/-how-to-keep-all-my-django-applications-in-specific-folderDoralynne
This works fine, but with this setup if you use SHELL_PLUS_SUBCLASSES_IMPORT of django-extensions will no longer work because django-extensions import the subclasses in the following way: from apps.AppName.serializers import ModelSerializer which triggers the following: RuntimeError: Model class apps.accounts.models.User doesn't declare an explicit app_labelUncivil
E
25

You can do this very easily, but you need to change the settings.py to look like this:

INSTALLED_APPS = (
    'apps.app1',
    'apps.app2',
    # ...
)

And your urls.py to look like this:

urlpatterns = patterns('', 
    (r'^app1/',include('apps.app1')),    
    (r'^app2/',include('apps.app2')),    
)

.. and modify any imports to point to the app location

Enalda answered 16/10, 2010 at 9:45 Comment(4)
I recommend against using this method, as it might lead to other apps not being able to reference your own application, and will require you to change all imports in your apps to point to the new directory. I think the right way is in Bernhard Vallant's answer.Universal
This same pattern is followed in django-oscar project.Undersell
I downvoted for the same reason as sleblanc - especially thinking about reusable models, where you might relate to a model using e.g. ForeignKey('appname.ModelName', ...) being upset by thisOutbrave
If you plan to use this convention in the mid of the development note that your migrations will create new tables in the database and won't map to the data you were working with.Cheltenham
A
22

How about you utilize the BASE_DIR variable already present in the settings.py.

Just add the following:

import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

Hope this helps.

Antitank answered 28/9, 2016 at 12:17 Comment(4)
Shouldn't BASE_DIR be un-quoted?Horlacher
Yes, my bad. I'll edit the answer. Thank you for pointing it out.Antitank
I think this should be the correct answer for Django 3.Doralynne
sadly this creates errors when creating models. django can not simply see the models inside the "apps.your_app" even if you enter this line...Bornstein
F
7

As a slight variant to Berhard Vallant's or Anshuman's answers, here is an alternative snippet to place in settings.py

import os
import sys  # Insert this line

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Insert the two lines below
APPS_DIR = os.path.join(BASE_DIR, '<your_project_dir_name>/apps/')
sys.path.insert(0, APPS_DIR)

Doing it in this way has the added benefit that your template directories are cleaner as they will look like below. Without the APPS_DIR variable, there will be a lot of repitition of <your_project_dir_name>/apps/ within the DIRS list of the TEMPLATES list.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(APPS_DIR, '<app_name>/templates/<app_name>'),
            os.path.join(APPS_DIR, '<app_name>/templates/<app_name>'),
            ...
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

You can list the apps within the INSTALLED_APPS list as normal with either the short-form name given in apps.py or by using the long-form syntax of appname.apps.AppnameConfig replacing appname with your app's name.

Fransis answered 7/3, 2020 at 19:16 Comment(0)
D
2

It's easy and simple you need to add to settings.py

import os
import sys

PROJECT_ROOT = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))

and edit your app config for example

old app config:

    class MyappConfig(AppConfig):
          default_auto_field = 'django.db.models.BigAutoField'
          name = 'myapp'

to new app config:

    class MyappConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        label='myapp'
        name = 'apps.myapp'

than installed apps example:

INSTALLED_APPS = [
     ...
     'apps.myapp.apps.MyappConfig'
     ...
]

I think it's very usefull and helpfull.Good luck :)

Downer answered 7/5, 2022 at 3:17 Comment(0)
F
1

If you're using virtualenv/virtualenvwrapper (which is a bit dated but still valid), you can use the included add2virtualenv command to augment your python path:

mkdir apps
cd apps
pwd
[/path/to/apps/dir]

Copy that path to clipboard, then:

add2virtualenv /path/to/apps/dir
Fugato answered 15/10, 2014 at 5:42 Comment(0)
P
1

Just add __init__.py (4 underscores in total) in your apps folder. Now you can just do

urlpatterns = [
        path('polls/',include('apps.polls.urls')),
        path('admin/', admin.site.urls)
]
Pocked answered 6/1, 2018 at 16:7 Comment(0)
H
0

In my case, my project folder structure is the following:

/project/
   /apps/
      /app1/
      /app2/
   /src/
      /settings.py
      ...

So I've solved it with these two lines on my settings.py:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(BASE_DIR, '../apps'))

No need to alter urls.py.

Housekeeper answered 25/6, 2020 at 18:56 Comment(0)
R
0

The following worked for me.

This is the folder structure:

/project1
    /apps
        /myapp

inside apps.py under /myapp:

class MyAppConfig(AppConfig):
    name = "apps.myapp"

In the settings.py:

INSTALLED_APPS = [
    ...
    "apps.myapp.apps.MyAppConfig",
]
Rosewater answered 5/3, 2023 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.