Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/rest_framework/settings.py: 67%
63 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2Settings for REST framework are all namespaced in the REST_FRAMEWORK setting.
3For example your project's `settings.py` file might look like this:
5REST_FRAMEWORK = {
6 'DEFAULT_RENDERER_CLASSES': [
7 'rest_framework.renderers.JSONRenderer',
8 'rest_framework.renderers.TemplateHTMLRenderer',
9 ],
10 'DEFAULT_PARSER_CLASSES': [
11 'rest_framework.parsers.JSONParser',
12 'rest_framework.parsers.FormParser',
13 'rest_framework.parsers.MultiPartParser',
14 ],
15}
17This module provides the `api_setting` object, that is used to access
18REST framework settings, checking for user settings first, then falling
19back to the defaults.
20"""
21from django.conf import settings
22from django.test.signals import setting_changed
23from django.utils.module_loading import import_string
25from rest_framework import ISO_8601
27DEFAULTS = {
28 # Base API policies
29 'DEFAULT_RENDERER_CLASSES': [
30 'rest_framework.renderers.JSONRenderer',
31 'rest_framework.renderers.BrowsableAPIRenderer',
32 ],
33 'DEFAULT_PARSER_CLASSES': [
34 'rest_framework.parsers.JSONParser',
35 'rest_framework.parsers.FormParser',
36 'rest_framework.parsers.MultiPartParser'
37 ],
38 'DEFAULT_AUTHENTICATION_CLASSES': [
39 'rest_framework.authentication.SessionAuthentication',
40 'rest_framework.authentication.BasicAuthentication'
41 ],
42 'DEFAULT_PERMISSION_CLASSES': [
43 'rest_framework.permissions.AllowAny',
44 ],
45 'DEFAULT_THROTTLE_CLASSES': [],
46 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
47 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata',
48 'DEFAULT_VERSIONING_CLASS': None,
50 # Generic view behavior
51 'DEFAULT_PAGINATION_CLASS': None,
52 'DEFAULT_FILTER_BACKENDS': [],
54 # Schema
55 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema',
57 # Throttling
58 'DEFAULT_THROTTLE_RATES': {
59 'user': None,
60 'anon': None,
61 },
62 'NUM_PROXIES': None,
64 # Pagination
65 'PAGE_SIZE': None,
67 # Filtering
68 'SEARCH_PARAM': 'search',
69 'ORDERING_PARAM': 'ordering',
71 # Versioning
72 'DEFAULT_VERSION': None,
73 'ALLOWED_VERSIONS': None,
74 'VERSION_PARAM': 'version',
76 # Authentication
77 'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
78 'UNAUTHENTICATED_TOKEN': None,
80 # View configuration
81 'VIEW_NAME_FUNCTION': 'rest_framework.views.get_view_name',
82 'VIEW_DESCRIPTION_FUNCTION': 'rest_framework.views.get_view_description',
84 # Exception handling
85 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
86 'NON_FIELD_ERRORS_KEY': 'non_field_errors',
88 # Testing
89 'TEST_REQUEST_RENDERER_CLASSES': [
90 'rest_framework.renderers.MultiPartRenderer',
91 'rest_framework.renderers.JSONRenderer'
92 ],
93 'TEST_REQUEST_DEFAULT_FORMAT': 'multipart',
95 # Hyperlink settings
96 'URL_FORMAT_OVERRIDE': 'format',
97 'FORMAT_SUFFIX_KWARG': 'format',
98 'URL_FIELD_NAME': 'url',
100 # Input and output formats
101 'DATE_FORMAT': ISO_8601,
102 'DATE_INPUT_FORMATS': [ISO_8601],
104 'DATETIME_FORMAT': ISO_8601,
105 'DATETIME_INPUT_FORMATS': [ISO_8601],
107 'TIME_FORMAT': ISO_8601,
108 'TIME_INPUT_FORMATS': [ISO_8601],
110 # Encoding
111 'UNICODE_JSON': True,
112 'COMPACT_JSON': True,
113 'STRICT_JSON': True,
114 'COERCE_DECIMAL_TO_STRING': True,
115 'UPLOADED_FILES_USE_URL': True,
117 # Browseable API
118 'HTML_SELECT_CUTOFF': 1000,
119 'HTML_SELECT_CUTOFF_TEXT': "More than {count} items...",
121 # Schemas
122 'SCHEMA_COERCE_PATH_PK': True,
123 'SCHEMA_COERCE_METHOD_NAMES': {
124 'retrieve': 'read',
125 'destroy': 'delete'
126 },
127}
130# List of settings that may be in string import notation.
131IMPORT_STRINGS = [
132 'DEFAULT_RENDERER_CLASSES',
133 'DEFAULT_PARSER_CLASSES',
134 'DEFAULT_AUTHENTICATION_CLASSES',
135 'DEFAULT_PERMISSION_CLASSES',
136 'DEFAULT_THROTTLE_CLASSES',
137 'DEFAULT_CONTENT_NEGOTIATION_CLASS',
138 'DEFAULT_METADATA_CLASS',
139 'DEFAULT_VERSIONING_CLASS',
140 'DEFAULT_PAGINATION_CLASS',
141 'DEFAULT_FILTER_BACKENDS',
142 'DEFAULT_SCHEMA_CLASS',
143 'EXCEPTION_HANDLER',
144 'TEST_REQUEST_RENDERER_CLASSES',
145 'UNAUTHENTICATED_USER',
146 'UNAUTHENTICATED_TOKEN',
147 'VIEW_NAME_FUNCTION',
148 'VIEW_DESCRIPTION_FUNCTION'
149]
152# List of settings that have been removed
153REMOVED_SETTINGS = [
154 'PAGINATE_BY', 'PAGINATE_BY_PARAM', 'MAX_PAGINATE_BY',
155]
158def perform_import(val, setting_name):
159 """
160 If the given setting is a string import notation,
161 then perform the necessary import or imports.
162 """
163 if val is None:
164 return None
165 elif isinstance(val, str):
166 return import_from_string(val, setting_name)
167 elif isinstance(val, (list, tuple)): 167 ↛ 169line 167 didn't jump to line 169, because the condition on line 167 was never false
168 return [import_from_string(item, setting_name) for item in val]
169 return val
172def import_from_string(val, setting_name):
173 """
174 Attempt to import a class from a string representation.
175 """
176 try:
177 return import_string(val)
178 except ImportError as e:
179 msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e)
180 raise ImportError(msg)
183class APISettings:
184 """
185 A settings object that allows REST Framework settings to be accessed as
186 properties. For example:
188 from rest_framework.settings import api_settings
189 print(api_settings.DEFAULT_RENDERER_CLASSES)
191 Any setting with string import paths will be automatically resolved
192 and return the class, rather than the string literal.
194 Note:
195 This is an internal class that is only compatible with settings namespaced
196 under the REST_FRAMEWORK name. It is not intended to be used by 3rd-party
197 apps, and test helpers like `override_settings` may not work as expected.
198 """
199 def __init__(self, user_settings=None, defaults=None, import_strings=None):
200 if user_settings: 200 ↛ 201line 200 didn't jump to line 201, because the condition on line 200 was never true
201 self._user_settings = self.__check_user_settings(user_settings)
202 self.defaults = defaults or DEFAULTS
203 self.import_strings = import_strings or IMPORT_STRINGS
204 self._cached_attrs = set()
206 @property
207 def user_settings(self):
208 if not hasattr(self, '_user_settings'):
209 self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
210 return self._user_settings
212 def __getattr__(self, attr):
213 if attr not in self.defaults:
214 raise AttributeError("Invalid API setting: '%s'" % attr)
216 try:
217 # Check if present in user settings
218 val = self.user_settings[attr]
219 except KeyError:
220 # Fall back to defaults
221 val = self.defaults[attr]
223 # Coerce import strings into classes
224 if attr in self.import_strings:
225 val = perform_import(val, attr)
227 # Cache the result
228 self._cached_attrs.add(attr)
229 setattr(self, attr, val)
230 return val
232 def __check_user_settings(self, user_settings):
233 SETTINGS_DOC = "https://www.django-rest-framework.org/api-guide/settings/"
234 for setting in REMOVED_SETTINGS:
235 if setting in user_settings:
236 raise RuntimeError("The '%s' setting has been removed. Please refer to '%s' for available settings." % (setting, SETTINGS_DOC))
237 return user_settings
239 def reload(self):
240 for attr in self._cached_attrs:
241 delattr(self, attr)
242 self._cached_attrs.clear()
243 if hasattr(self, '_user_settings'):
244 delattr(self, '_user_settings')
247api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
250def reload_api_settings(*args, **kwargs):
251 setting = kwargs['setting']
252 if setting == 'REST_FRAMEWORK':
253 api_settings.reload()
256setting_changed.connect(reload_api_settings)