Moving django apps into subfolder and url.py error
Asked Answered
U

4

16

I have a question about putting django apps into "apps" subdirectory. I have the app called “faktura” in a project_root. I didn’t like the fact it lies there and I want to store all my apps under “apps” subdirectory.

So, I found out that I could extend python path to “apps” subdir, so after looking in the internet, I added this string to settings.py: sys.path.insert(0, os.path.join(PROJECT_PATH, "apps")). Then I added the app to INSTALLED_APPS like “faktura”. Everything worked smooth until I added url(r'^faktura/', include('faktura.urls')) to urls.py in the root. Since that, Django throws the error message “No module named faktura” full taceback is here: http://dpaste.com/737380/

What can be wrong here, why only urls.py can’t find the app? And does it can’t find this app if I added it to the PATH? I spent a morning trying to figure out what’s wrong and now I need your help.

Uppsala answered 25/4, 2012 at 10:6 Comment(0)
C
25

I don't know why the previous answer got -1 aside from maybe a few redundant lines that can be corrected. Anyway, I found a slightly different method that doesn't involve adding anything to the python path.

This is my final directory structure, I will explain in a moment:

mysite
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── apps
│   ├── __init__.py
│   └── myfirstapp
│       ├── __init__.py
│       ├── admin.py
│       ├── models.py
│       ├── tests.py
│       └── views.py
└── manage.py

No matter if you have just created your project or if you want to move your apps, create the apps subdirectory that should contain your apps. The trick is to add an __init__.py to that directory.

mkdir apps
touch apps/__init__.py

Now you can move your existing apps into the apps subdirectory. If you would like to create a new one instead here are the commands:

python manage.py mysecondapp
mv mysecondapp apps/

Warning: Don't be tempted to call python manage.py ./apps/mysecondapp. For some reason this deletes all other apps in that directory. I just lost a day of work this way.

Next, you will need to fix a few imports. Your settings.py should be prefixed with apps:

INSTALLED_APPS = (
    ...
    'apps.myfirstapp',
    'apps.mysecondapp'
)

Lastly, fix your project's urls.py to prefix apps:

urlpatterns = patterns('', 
  url(r'^myfirstapp', include('apps.myfirstapp.urls')),
  ...
)

Depending on how you wrote them, you might also have to fix a few imports inside your app. Either just use from models import MyFirstModel or also prefix it using from apps.myfirstapp.models import MyFirstModel.

In short, if you make your apps directory a python package (by adding __init__.py), you can use it as part of the import path. This should work regardless of the deployment method with no extra configuration.

Contemporize answered 26/1, 2014 at 10:1 Comment(4)
I ran into a problem that wasn't addressed in this answer, in that the urls.py in apps/myfirstapp needed to have the first argument of patterns(...) set to 'apps.myfirstapp', as before I moved it, it read only 'myfirstapp'. Django's debug output was much less than helpful for this.Densitometer
from apps.myfirstapp.models import MyFirstModel not working in the secondapps models file..don't know why..Cowpea
Note that you can't use apps.myfirstapp.apps.MyfirstappConfig in INSTALLED_APPSCoeternity
@ReinstateMonica Why we cannot use Config?Hispid
I
3

Use BASE_DIR variable from the settings.py. It should be already defined:

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

Better not use the __file__ attribute in manage.py and wsgi.py, as they are located in different directories.

So, just add the following to manage.py and wsgi.py (and to the celery.py if you use Celery):

    from django.conf import settings
    sys.path.append(os.path.join(settings.BASE_DIR, "apps"))

You will end up with the following project structure:

project
├── project
│   ├── __init__.py
│   ├── celery.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── apps
│   ├── app1
│   └── app2
└── manage.py
Ideo answered 22/1, 2017 at 22:23 Comment(0)
M
1

To keep your Django applications in a subfolder (such as apps/), first add the following to your settings.py:

import os

PROJECT_ROOT = os.path.dirname(__file__)

Then in manage.py:

Right under #!/usr/bin/env python add:

import sys

from os.path import abspath, dirname, join

from site import addsitedir

Right before if __name__ == "__main__" : add:

sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))

Monody answered 25/4, 2012 at 10:24 Comment(2)
Yep this works... but if you use - like I do - uwsgi as a app server then you should ALSO apply the insert into the wsgi.py file.Giacinta
Do you really need the unused imports (addsitedir, dirname, abspath)? Or are they left over from a previous version of this answer?Edify
B
0

@Radu Gheorghiu's answer; It is not necessary to edit settings.py, and the insert path line can be condensed to 1 line of code.

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "apps"))

I sourced this answer from http://obroll.com/nested-application-inside-apps-sub-folder-in-django-1-3/

Brookins answered 3/7, 2014 at 6:8 Comment(1)
Please do not create an answer on an answer. If you want to add something to Radu's answer, use the comment function.Brnaba

© 2022 - 2024 — McMap. All rights reserved.