Skip to content

Reload api_settings when using Django's 'override_settings'#2473

Merged
lovelydinosaur merged 1 commit intomasterfrom
reload-settings
Jan 28, 2015
Merged

Reload api_settings when using Django's 'override_settings'#2473
lovelydinosaur merged 1 commit intomasterfrom
reload-settings

Conversation

@lovelydinosaur
Copy link
Contributor

Closes #2466, however not yet entirely happy with this.

Note that various REST framework views set class attributes such as...

renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES

Effect of this is that if rest_framework.views has been imported then changing api_settings isn't enough, as APIView.renderer_classes (and others) have already been set.

The two tests using override_settings in this pull request use reload_module to ensure that the required REST framework modules are reloaded to get the new settings.

Possible approaches to solve:

  • api_settings.something returns a lazy object. (Or wrap the class declarations)
  • Only access api_settings inside running code, not inside class declarations.
  • Document the constraint, possibly adding a helper function for reloading required modules.
  • Automagically reload the required modules (had a look at this and not overly keen on it)

@lovelydinosaur
Copy link
Contributor Author

Based on reviewing django code I'm tempted to consider "Only access api_settings inside running code, not inside class declarations." as a possibility. Note potential conflict of that approach with #2470.

@adamchainz
Copy link
Contributor

My suggestion would be not to complicate things with reloading; since api_settings is a singleton object in the module, can you not change it to always look directly at django's settings, rather than copying them to USER_SETTINGS at import time? If you change
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/settings.py#L186 to read val = settings.REST_FRAMEWORK[attr] you're halfway there.

@lovelydinosaur
Copy link
Contributor Author

We could although that wouldn't solve the class attributes that we set, such as APIView.renderer_classes. Those would still be evaluated at module import time.

@jamescooke
Copy link
Contributor

Tom this PR is very helpful.

Going over the four options outlined - ordering them from worst to best in my opinion:

  • "Automagically reload the required modules" - 👎 I think this would be horrible and agree it's not good.
  • "api_settings.something returns a lazy object" ... Not sure if this is the Django way of building settings - could be confusing and long to implement.
  • "Document the constraint, possibly adding a helper function..." - Basic solution and would be good, but won't work in all cases, such as where views are already loaded, as mentioned. Would help to alleviate some of the unexpected behaviour shock factor.
  • "Only access api_settings inside running code, not inside class declarations" - 👍 for this. It seems the most Django-ish.

The 'runtime only' solution could probably be phased in over releases, and if there was documentation of the issue in the testing section of the site, this would create space for explaining which settings may not take effect when adjusted with override_settings.

Document now with helper and then work towards to 'runtime only' seems like a nice way to progress to me.

@lovelydinosaur
Copy link
Contributor Author

Document now with helper and then work towards to 'runtime only' seems like a nice way to progress to me.

@jamescooke Sounds sensible to me, yup! Esp the incremental approach.

lovelydinosaur added a commit that referenced this pull request Jan 28, 2015
Reload api_settings when using Django's 'override_settings'
@lovelydinosaur lovelydinosaur merged commit 761f264 into master Jan 28, 2015
@lovelydinosaur lovelydinosaur deleted the reload-settings branch January 28, 2015 09:05
@adamchainz
Copy link
Contributor

👍

@joeelizondo
Copy link

Is there a way to reload the DEFAULT_AUTHENTICATION_CLASSES and DEFAULT_PERMISSION_CLASSES when the view is defined as function with the @api_view['GET'] decorator?

AndriIushchuk added a commit to django-stars/django-rest-framework-jwt that referenced this pull request Nov 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Settings should be updated when overridden in Django tests

4 participants