Heroku application structure for Django - django

I started a Django 1.6 application locally, with the structure that it came with:
project
django_folder
wsgi.py
my_app
views.py
models.py
...
my_second_app
views.py
models.py
...
Now when I try and deploy on Heroku, it only seems to work with the Procfile in the top directory. I seem to be able to move manage.py around without problems.
My problem is that I have environmental variables set so that in my_app views.py I do the following:
from models import my_model
When I put it on Heroku, it seems that I need to specify my_app
from my_app.models import my_model
Is it possible to set an environmental variable in Heroku so I don't need the myapp in front of models? (My second app is not finished, but partly integrated. It is going to be a pain to change all the imports in both apps). When I add my_app in settings.py is this supposed to affect import paths?

You don't need environment variables, just use relative imports. So in your views.py:
from .models import MyModel
Note the leading dot making this a relative import. In this case there's no need to do anything more. This is the standard pythonic way of doing things.

Related

How to keep out utility functions in a separate directory inside an app in Django

In my current project, I have moved out most of the business logic from my views and have put them under the following directory structure myapp/utility/utility.py. Under the Utility directory i have put the init.py file also. I am using most of the models from my Models.py file in the utils.py file. Now the problem I am facing is when I run python manage.py runserver, it throws up an error saying models not found.
I had also followed the steps listed in the Django docs here. The project structure can be seen below. The following are just below my app directory.
In the utils.py I am trying to do the import
from my_project.myapp.models import Location, Product
This where it is not working.
In Django you may import from project's root directory directly, so in your case it should be something like this:
from myapp.models import Location, Product

Django single-test migration

I have recently implemented a reusable app within the django project I am working on. For the sake of the question, let's call it reusable_app. This app also has some unittests that run, however, these tests depend on some basic models declared somewhere next to the tests in a model.py.
/resuable_app
__init__.py
models.py
views.py
urls.py
/tests
__init__.py
tests.py
/simple_app
__init__.py
models.py
Now, the models aren't loaded in the database unless I specify the folder in INSTALLED_APPS in the testing configuration file. I was wondering if there is another way to achieve this, not having to expose the app in the settings file? I seem to be able to specify the app via #override_settings, but the migrations are not ran.
Ex:
#override_settings(INSTALLED_APPS=['reusable_app'])
class TestReusableApp(TestCase):
def test_something(self):
...
If reusable_app is not specified in the settings module INSTALLED_APPS this still yields a ProgrammingError. Am I missing something or is there another approach?
I think the issue here is that the test runner is setting up the tables before you add the app with #override_settings.
Normally what I do with reusable apps is to run the tests in the context of an "example" app, with settings that include the app your want to test. Usually works pretty well, as I'm packaging the reusable app separately. Here's an example of this from a past project of mine.
However, if that's not possible, you might try to override setUp in your tests, and call the "migrate" command within that code. For example:
from django.core.management import call_command
#override_settings(INSTALLED_APPS=['reusable_app'])
MyTestCase(TestCase):
def setUp(self):
call_command('migrate', 'reusable_app')
This is a bit messy, but it might be worth trying. Depending on how things go, you might also have to run django.setup().

Migrate models in package hierachy without South

I'm on Django 1.8. Rather than all my models being in a single models.py file, I have them in a package that looks like this:
models/
- __init__.py
- Album.py
- Artist.py
But Django's makemigrations command appears to work only when an app has a single models.py file. Running django-admin help makemigrations does not bring up any hints on additional options that I can pass to the command to achieve what I want. Also, all other questions and answers I've seen here on SO involve South, which is incompatible with Django 1.8.
So what's the workaround?
Horizontally splitting django models across multiple files is a valid approach. A good explanation can be found here.
Django looks for your models in the models module which can be a file or a valid python package.
If you have a valid python package( a directory with a __init__.py file) it will try to discover the models based on the contents of __init__.py.
Make sure that your __init__.py file looks like this:
from Album import Album
from Artist import Artist
Then django should discover your models correctly.
In your models.py
add.
# myproject/app/models.py:
from models/Album.py import *
from models/Artist.py import *
Note about django-south: From django-1.7 migrations has been started supported. Please check Migrations.

PyCharm cannot resolve reference in __init__.py with Django project apps

I am at my wits end with this issue, and would love some help resolving this.
I have a Django project with a bunch of sub apps as such:
my_project/
manage.py
my_project/
settings.py
urls.py
wsgi.py
app_root/
__init__.py
app1/
__init__.py
models.py
views.py
urls.py
templates/
[various templates].html
app2/
__init__.py
models.py
[etc]
app3/
[etc]
in my django settings.py i have installed apps as such:
app_root.app1,
app_root.app2,
In PyCharm, I've tried various things but essentially have Content Root as the top "my_project/" and app_root, app1, app2, etc as Source Roots. I've tried just having app_root as the only Source Root, and I've tried having only app1, app2, etc only as Source Roots, but nothing makes any difference.
Everything functions fine. app runs and everything. However, PyCharm has an inability to resolve my apps.
However, if i try this:
import app_root
...
def some_function(self):
app_root.app1.models.My_Model.objects.all()
it will highlight app1 with the error "Cannot find reference 'app1' in '__init__.py'"
This also means it can't do autocomplete anywhere in the path while doing app_root.app1. - it has no idea about models, views, etc. despite having an (empty) __init__.py in every directory.
I also cannot use any refactoring because it always says "Function is not under the source root"
I've spent countless hours trying to get PyCharm to behave but simply cannot find a way to do it. Is there any way this can be done so PyCharm will autocomplete my apps and not keep giving inspection warnings?
I had some similar issues. My solution; within the PyCharm preferences I added a path to app_root in my active Python Interpreter.
After an exchange with the PyCharm folks, here is what I learned:
Django imports all apps in INSTALLED_APPS variable and their models using __import__ for its own purposes.
In your case, it runs
__import__("app_root.app1")
__import__("app_root.app1.models")
After that, you call import app_root and obtain module app_root with app_root.app1 and app_root.app1.models already imported by internal Django code
Fact that Django imports apps and models is Django internals, it is undocumented and may be changed in future releases. We believe you should not rely on it in your production code, nor PyCharm should.
Here is example in bare python (no django):
__import__("encodings.ascii")
import encodings
print (encodings.ascii.Codec) # this code works, but PyCharm marks "ascii" as "unknown module"
So basically, it's not supposed to work as import app_root, but Django funkiness is masking that.

How to deal with heroku renaming my root-level app?

Heroku seems to prefer the apps deployed have a certain structure, mostly that the .git and manage.py is at root level and everything else is below that.
I have inherited a Django app I'm trying to deploy for testing purposes and I don't think I can restructure it so I was wondering if I have an alternative.
The structure I've inherited has most of the files in the root folder:
./foo:
__init__.py,
.git,
Procfile,
settings.py,
manage.py,
bar/
models.py, etc
From within foo I can run python manage.py shell and in there from foo.bar import models works.
However, when I push this to Heroku, it puts the root in /app, so foo becomes app and from foo.bar import models no longer works.
Is there any magic settings that would allow me to indicate that app is really foo and allow me to continue without refactoring the app structure and/or all the imports?
Similar question: I think my question is similar to Heroku - Django: Had to change every mentioning of myproject into app to get my site working. How to best avoid this in the future?, except I'm asking if there's anything I can do without changing the site structure.
You can try adding a line to manage.py that modifies sys.path to make sure that foo is in your path:
import sys
PROJECT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
if PROJECT_DIR not in sys.path:
sys.path.insert(0, PROJECT_DIR)
Although as a side note its not really good django style to have your toplevel directory be a python module, precisely because it makes deployment more complicated (I'm not POSITIVE that the above will work on heroku). I might recommend just changing your code to import from bar directly and removing foo/__init__.py.
The easiest way would be to delete foo/__init__.py and modify your import statements to import from bar instead of from foo, eg
from foo.bar.models import *
becomes
from bar.models import *
Alternatively you can use relative imports. So if you wanted to import bar.models in bar.views, you'd do
from .models import *
The reason this is an issue is that Django 1.4 changed folder structure for newly created projects. Before 1.4 you'd have a similar structure like you described, minus foo/__init__.py. Heroku adapted Django 1.4's project structure, which is arguably better because it encapsulates the settings within the project and makes it more portable.