Skip to content

Add json api settings module #419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions example/tests/test_generic_viewset.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
from django.conf import settings
from django.test import override_settings
from django.urls import reverse

from example.tests import TestBase


@override_settings(JSON_API_FORMAT_KEYS='dasherize')
class GenericViewSet(TestBase):
"""
Test expected responses coming from a Generic ViewSet
"""

def setUp(self):
super(GenericViewSet, self).setUp()

setattr(settings, 'JSON_API_FORMAT_KEYS', 'dasherize')

def tearDown(self):

setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')

def test_default_rest_framework_behavior(self):
"""
This is more of an example really, showing default behavior
Expand Down
9 changes: 2 additions & 7 deletions example/tests/test_model_viewsets.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import pytest
from django.conf import settings
from django.contrib.auth import get_user_model
from django.test import override_settings
from django.urls import reverse
from django.utils import encoding

from example.tests import TestBase


@override_settings(JSON_API_FORMAT_KEYS='dasherize')
class ModelViewSetTests(TestBase):
"""
Test usage with ModelViewSets, also tests pluralization, camelization,
Expand All @@ -21,12 +22,6 @@ def setUp(self):
super(ModelViewSetTests, self).setUp()
self.detail_url = reverse('user-detail', kwargs={'pk': self.miles.pk})

setattr(settings, 'JSON_API_FORMAT_KEYS', 'dasherize')

def tearDown(self):

setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')

def test_key_in_list_result(self):
"""
Ensure the result has a 'user' key since that is the name of the model
Expand Down
17 changes: 17 additions & 0 deletions example/tests/unit/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest

from rest_framework_json_api.settings import json_api_settings


def test_settings_invalid():
with pytest.raises(AttributeError):
json_api_settings.INVALID_SETTING


def test_settings_default():
assert json_api_settings.UNIFORM_EXCEPTIONS is False


def test_settings_override(settings):
settings.JSON_API_FORMAT_KEYS = 'dasherize'
assert json_api_settings.FORMAT_KEYS == 'dasherize'
10 changes: 5 additions & 5 deletions example/tests/unit/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from django.conf import settings
from django.contrib.auth import get_user_model
from django.test import override_settings
from django.utils import six
from rest_framework import serializers
from rest_framework.generics import GenericAPIView
Expand Down Expand Up @@ -29,12 +29,12 @@ class Meta:
def test_get_resource_name():
view = APIView()
context = {'view': view}
setattr(settings, 'JSON_API_FORMAT_TYPES', None)
assert 'APIViews' == utils.get_resource_name(context), 'not formatted'
with override_settings(JSON_API_FORMAT_TYPES=None):
assert 'APIViews' == utils.get_resource_name(context), 'not formatted'

context = {'view': view}
setattr(settings, 'JSON_API_FORMAT_TYPES', 'dasherize')
assert 'api-views' == utils.get_resource_name(context), 'derived from view'
with override_settings(JSON_API_FORMAT_TYPES='dasherize'):
assert 'api-views' == utils.get_resource_name(context), 'derived from view'

view.model = get_user_model()
assert 'users' == utils.get_resource_name(context), 'derived from view model'
Expand Down
5 changes: 3 additions & 2 deletions rest_framework_json_api/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions, status

from rest_framework_json_api import utils

from .settings import json_api_settings


def rendered_with_json_api(view):
from rest_framework_json_api.renderers import JSONRenderer
Expand All @@ -29,7 +30,7 @@ def exception_handler(exc, context):

# Use regular DRF format if not rendered by DRF JSON API and not uniform
is_json_api_view = rendered_with_json_api(context['view'])
is_uniform = getattr(settings, 'JSON_API_UNIFORM_EXCEPTIONS', False)
is_uniform = json_api_settings.UNIFORM_EXCEPTIONS
if not is_json_api_view and not is_uniform:
return response

Expand Down
6 changes: 3 additions & 3 deletions rest_framework_json_api/parsers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
Parsers
"""
from django.conf import settings
from django.utils import six
from rest_framework import parsers
from rest_framework.exceptions import ParseError

from . import exceptions, renderers, serializers, utils
from .settings import json_api_settings


class JSONParser(parsers.JSONParser):
Expand All @@ -32,7 +32,7 @@ class JSONParser(parsers.JSONParser):
@staticmethod
def parse_attributes(data):
attributes = data.get('attributes')
uses_format_translation = getattr(settings, 'JSON_API_FORMAT_KEYS', False)
uses_format_translation = json_api_settings.FORMAT_KEYS

if not attributes:
return dict()
Expand All @@ -44,7 +44,7 @@ def parse_attributes(data):

@staticmethod
def parse_relationships(data):
uses_format_translation = getattr(settings, 'JSON_API_FORMAT_KEYS', False)
uses_format_translation = json_api_settings.FORMAT_KEYS
relationships = data.get('relationships')

if not relationships:
Expand Down
57 changes: 57 additions & 0 deletions rest_framework_json_api/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
This module provides the `json_api_settings` object that is used to access
JSON API REST framework settings, checking for user settings first, then falling back to
the defaults.
"""

from django.conf import settings
from django.core.signals import setting_changed

JSON_API_SETTINGS_PREFIX = 'JSON_API_'

DEFAULTS = {
'FORMAT_KEYS': False,
'FORMAT_RELATION_KEYS': None,
'FORMAT_TYPES': False,
'PLURALIZE_RELATION_TYPE': None,
'PLURALIZE_TYPES': False,
'UNIFORM_EXCEPTIONS': False,
}


class JSONAPISettings(object):
"""
A settings object that allows json api settings to be access as
properties.
"""

def __init__(self, user_settings=settings, defaults=DEFAULTS):
self.defaults = defaults
self.user_settings = user_settings

def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid JSON API setting: '%s'" % attr)

value = getattr(self.user_settings, JSON_API_SETTINGS_PREFIX + attr, self.defaults[attr])

# Cache the result
setattr(self, attr, value)
return value


json_api_settings = JSONAPISettings()


def reload_json_api_settings(*args, **kwargs):
django_setting = kwargs['setting']
setting = django_setting.replace(JSON_API_SETTINGS_PREFIX, '')
value = kwargs['value']
if setting in DEFAULTS.keys():
if value is not None:
setattr(json_api_settings, setting, value)
elif hasattr(json_api_settings, setting):
delattr(json_api_settings, setting)


setting_changed.connect(reload_json_api_settings)
14 changes: 8 additions & 6 deletions rest_framework_json_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from rest_framework.exceptions import APIException
from rest_framework.serializers import ManyRelatedField # noqa: F401

from .settings import json_api_settings

try:
from rest_framework_nested.relations import HyperlinkedRouterField
except ImportError:
Expand Down Expand Up @@ -104,7 +106,7 @@ def format_keys(obj, format_type=None):
:format_type: Either 'dasherize', 'camelize' or 'underscore'
"""
if format_type is None:
format_type = getattr(settings, 'JSON_API_FORMAT_KEYS', False)
format_type = json_api_settings.FORMAT_KEYS

if format_type in ('dasherize', 'camelize', 'underscore', 'capitalize'):

Expand Down Expand Up @@ -136,7 +138,7 @@ def format_keys(obj, format_type=None):

def format_value(value, format_type=None):
if format_type is None:
format_type = getattr(settings, 'JSON_API_FORMAT_KEYS', False)
format_type = json_api_settings.FORMAT_KEYS
if format_type == 'dasherize':
# inflection can't dasherize camelCase
value = inflection.underscore(value)
Expand All @@ -156,17 +158,17 @@ def format_relation_name(value, format_type=None):
"settings are now 'JSON_API_FORMAT_TYPES' and 'JSON_API_PLURALIZE_TYPES'"
)
if format_type is None:
format_type = getattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', None)
pluralize = getattr(settings, 'JSON_API_PLURALIZE_RELATION_TYPE', None)
format_type = json_api_settings.FORMAT_RELATION_KEYS
pluralize = json_api_settings.PLURALIZE_RELATION_TYPE
return format_resource_type(value, format_type, pluralize)


def format_resource_type(value, format_type=None, pluralize=None):
if format_type is None:
format_type = getattr(settings, 'JSON_API_FORMAT_TYPES', False)
format_type = json_api_settings.FORMAT_TYPES

if pluralize is None:
pluralize = getattr(settings, 'JSON_API_PLURALIZE_TYPES', False)
pluralize = json_api_settings.PLURALIZE_TYPES

if format_type:
# format_type will never be None here so we can use format_value
Expand Down