1

I ran into an issue regarding app specific settings.

I've got two Django projects, P1, and P2, each of them running in their own virtual env. P2 uses some models from the apps of P1, so I used add2virtualenv (thanks to virtualenvwrapper) to tackle with depedencies.

The issue is that some of these P1 apps are relying on custom settings (simply located in p1/project/settings.py, nothing fancy so far) which obviously strongly bother P2's execution.

For instance, when I run P2's tests:

$ ./p2/manage.py test

Traceback (most recent call last):
  File "./manage.py", line 11, in <module>
    execute_from_command_line(sys.argv)
  [...]
AttributeError: 'Settings' object has no attribute 'SOME_P1_APP_CUSTOM_SETTING'

How am I supposed to deal with that ? Is it broken by design, or does Django provide something elegant to handle the distribution of app specific settings ?
I'd like to avoid copy/pasting these settings in every project that requires them.

Anto
  • 6,806
  • 8
  • 43
  • 65
  • As mentioned in [another answer](http://stackoverflow.com/a/9446940/1030960), I might use `getattr()` with some default value, but it doesn't really make sense here. – Anto Apr 09 '14 at 22:44
  • It seems like they're fairly interdependent -- are you sure you need to have them in their own virtualenvs? – Two-Bit Alchemist Apr 09 '14 at 22:46
  • Mhmm, yes it makes sense to me: one is a backend handling data while the other one is a service over the said data. – Anto Apr 09 '14 at 22:48
  • [This snippet](https://djangosnippets.org/snippets/573/) seems to address the issue, but not convinced by the general design. [This blog post](http://chrisburnor.com/app-specific-settings-for-django) might be the solution, but I'm not sure it will fit the way we template and deploy projects settings. – Anto Apr 09 '14 at 22:55
  • Are you Able to run django Server for P2 Project ? This problem looks to be for the the commands run using manage.py – Sahil kalra Apr 21 '14 at 10:35

4 Answers4

2

If you've got two apps, one a backend and another a service which uses it, I'd recommend you mock the backend when testing the service which uses it. That's the key to the issue here: you're trying to run tests for Thing A which also needs Thing B to be running, and that's not really catered for by the Django testserver (which is what runs under the surface when you're executing tests).

So, yes, you need to fake the backend when testing the service (and vice versa).

There are various ways to do this, including using Python's 'mock' library to mock out the API of the other app (or, more specifically, mock the functions in MyService which talk to MyBackend) and return data objects that fit with whatever behaviour you're trying to test. Those fake responses could be based on actual test fixtures loaded from JSON dumped from other app, potentially.

To make life easier, you could also write a few tests in the backend repo to ensure that the schema for the mock backend data actually matches the schema of the real backend, which would avoid regressions if one or both apps changes. If you do use a fixture for that data, storing that mock data in an intermediary repo (and then including it as an external dependency of your codebase) would be one way to ensure that it's available to both codebases without needing the actual other codebase to be installed and running alongside it during tests.

Steve Jalim
  • 11,989
  • 1
  • 37
  • 54
  • Thanks for the answer, but the question is more about how to distribute a Django app that requires specific settings. I don't directly have issues with the test framework (it provides [a simple tool to handle settings](https://docs.djangoproject.com/en/1.6/topics/testing/tools/#overriding-settings)) – Anto Apr 21 '14 at 19:50
1

I would use three different settings files: A common file used by the two projects and other two settings files (each one for project) that imports the common one and override or extends it with proper attributes.

It is a common practice to divide the settings file for dev or prod environment and import a common one settings. You can see a sample from django-skel project.

In each one of the two settings you can import everything from the common:

from common import *
Leonardo
  • 4,046
  • 5
  • 44
  • 85
  • Thanks for the answer, but I don't have any issues with different environments settings. Once again, the question is about how to distribute a Django app that requires specific settings. – Anto Apr 21 '14 at 19:53
  • That was just an example, you can apply the same principle to your case. Instead of having multiple settings for multiple environments you can have a central common settings for your whole project and two different settings files for each one of your "subproject" that use most of their properties from the common one and override or extends some of its properties – Leonardo Apr 22 '14 at 08:53
0

1. One Quick and feasible solution is to Filter out all settings from P1, which are required for P2's execution and Put it in common.py

And In P2, either import common.py from P1

#### P2/settings.py ####
from p1.commons import *

or

Copy the common.py settings file to P2 and import.

#### P2/settings.py ####
from commons import *

2. If this the problem only with the Test runner. then I would recommend you to create a test_settings.py which would import from settings.py in P2:

#### P2/test_settings.py ####
from settings import *

### Put here all extra settings required for the P2's test execution

and use it to run Test using --settings option e.g.

.p2/manage.py --setting=test_settings test

A well structured Settings file structure is always preferred for non buggy Application. You can follow django-skel for more insight into a good settings structure

Sahil kalra
  • 8,344
  • 4
  • 23
  • 29
0

The possible solutions I found accross the web:

  1. Always access settings by calling getattr() with a default value.
    Pro: simple, elegant, sounds like a good practice.
    Con: won't help with settings for which a default value doesn't make sense (like an API key).
  2. Use a third party solution like django-appconf or django-appsettings.
    Pro: keeps you from diving too deep into the problematic. Con: some might find it quite overwhelming.
  3. Put the specific extra settings __init__.py file in the app root, like suggested in Chris Burnor's post.
    Pro: clearly highlights you app's settings, makes it easy to find and to ship Con: might be a hell to deploy if you use a templating system; also might be a bit misleading since it's not such a well known practice (to my knowledge).
  4. Introduce some logic around your settings handling, like in this snippet.
    Pro: does the job.
    Con: logic doesn't have anything to do there.
Anto
  • 6,806
  • 8
  • 43
  • 65