In my Django project's urlconf I have something like this:
from django.conf import settings
from django.conf.urls import include, url
urlpatterns = [
url(r'^{}/blog'.format(settings.MY_ROOT_DIR),
include('weblogs.urls')),
# ...
]
In my settings.py
I'll have something like:
MY_ROOT_DIR = 'phil'
This is so I can set the root directory, that's used in several places, in one place (the settings).
When I come to test URLs, I use the @override_settings
decorator:
from django.test import TestCase, override_settings
from django.urls import reverse
@override_settings(MY_ROOT_DIR='terry')
class WeblogUrlsTestCase(TestCase):
def test_post_detail_url(self):
self.assertEqual(
reverse('post_detail', kwargs={'slug': 'my-post'}),
'/terry/blog/my-post/'
)
However, @override_settings
doesn't appear to do anything - the MY_ROOT_DIR
value used in urls.py
is always "phil"
, never the overridden setting of "terry"
. I've also tried @modify_settings
, and using it on the test method, rather than the class.
I guess the urlconf is is loaded by Django before @override_settings
takes effect? Is there a way around this? Or a better solution altogether?
As you guessed, you have overriden settings after they have already been imported in urls. This would have worked if you had used the settings
variable inside some method, and not in global scope of urls.py
.
Although overriding settings configuration on runtime might seem convenient, in my opinion, you should create a separate file for testing. This saves a lot of configuration for testing and this would ensure that you never end up doing something irreversible (like cleaning staging database).
# test_settings.py
MY_ROOT_DIR = 'terry'
Say your testing file exists in 'my_project/test_settings.py', add
settings = 'my_project.test_settings' if 'test' in sys.argv else 'my_project.settings'
in your manage.py. This will ensure that when you run python manage.py test
you use test_settings only. If you are using some other testing client like pytest, you could as easily add this to pytest.ini