vbabiy / djangorestframework-camel-case Goto Github PK
View Code? Open in Web Editor NEWCamel case JSON support for Django REST framework.
License: Other
Camel case JSON support for Django REST framework.
License: Other
>>> underscoreize({'HelloWord': 'HelloWorld'})
{'_hello_word': 'HelloWorld'}
Am i using it a wrong way?
I got data from an API and this problem confused me.
It seems no other issue refer to this case.
Sorry about my bad English, and thanks for your work.
I am using the library already so I would like to use the underscore_to_camel
too.
but its not working with strings.
Getting *** AttributeError: 'str' object has no attribute 'group'
error
When you install version 1.0.3 from PyPI by pip install djangorestframework-camel-case you get completely different code than on GitHub.
Few examples of differencies:
render module is missing class CamelCaseBrowsableAPIRenderer
parser module contains: from rest_framework.parsers import six, FormParser
Hi everyone,
Thanks for maintaining such a great resource.
Unfortunately, I am having trouble getting this package to work with Django Rest Witchcraft which handles serializing models against SQLAlchemy.
Problem
I have added the default renderer and parser classes to my settings.py
as follows (following the instructions in the README.md
:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': os.environ.get('PAGINATION_SIZE'),
'DEFAULT_RENDERER_CLASSES': (
'djangorestframework_camel_case.render.CamelCaseJSONRenderer',
'djangorestframework_camel_case.render.CamelCaseBrowsableAPIRenderer',
# Continue renders
),
'DEFAULT_PARSER_CLASSES': (
'djangorestframework_camel_case.parser.CamelCaseFormParser',
'djangorestframework_camel_case.parser.CamelCaseMultiPartParser',
'djangorestframework_camel_case.parser.CamelCaseJSONParser',
# continue parsers
),
}
I am also using Yet another Swagger generator to generate docs for the API.
Both the docs, swagger and ReDoc, and the corresponding json
output still show underscores in my request.
Question
What areas should I look in for as to why the parser/renderer is not parsing the camelCase output as expected?
With an input like _leading_underscore
, camelize
gives an output of LeadingUnderscore
, with the first letter as uppercase.
Expected output is leadingUnderscore
with the first letter as 3lowercase.
As it says in Django REST Framework documentation
.data
The unrendered content of a Request object.
Unfortunatelly it occurs that CamelCaseJSONRenderer
is changing response.data
from
{ 'abc_def': True }
into
{ 'abcDef': True }
For minimal example see: https://github.com/magul/drf-cc-26 (there are 4 tests and 1 is failing because of the issue).
When the value to render is a translation (ugettext_lazy) the string is converted to array of strings.
I think the problem is the is_iterable method in util.py, because return true when the value is a translation.
Example of response:
{
"detail": [
"S",
"e",
" ",
"h",
"a",
" ",
"e",
"n",
"v",
"i",
"a",
"d",
"o",
" ",
"u",
"n",
" ",
"c",
"o",
"r",
"r",
"e",
"o",
" ",
"e",
"l",
"e",
"c",
"t",
"r",
"ó",
"n",
"i",
"c",
"o",
" ",
"p",
"a",
"r",
"a",
" ",
"r",
"e",
"s",
"t",
"a",
"b",
"l",
"e",
"c",
"e",
"r",
" ",
"l",
"a",
" ",
"c",
"o",
"n",
"t",
"r",
"a",
"s",
"e",
"ñ",
"a",
"."
]
}
We define some serializer field contains number like password1
, the serializer can't detect field and raise required error.
We define the endpoint to change password. The Serializer has two fields, i.e.
, then post to it with the body as
{
"newPassword1": "hogehoge",
"newPassword2": "hogehoge"
}
. We have required field error
like
Downgrade djangorestframework-camel-case
to 0.2.0, it works.
When I try to upload multiple files in the same key of request body underscoreize
function replace all files with the last one.
The variant with leading dot should work in Python 2.5 and later, and so should be valid for all supported versions.
It has apparently been fixed in a fork at https://github.com/ondrowan/djangorestframework-camel-case/commit/ca044d46682f58d80e9f099d31a663f98ec85ae2
... so I guess it wouldn't make sense for me to make a pull request with the same change...?
Hello and thanks for making this package! I have a field that exists as a tuple before being serialized to a list. With drf-camel-case, there is an exception coming from the camelize function:
if isinstance(data, (list, tuple)):
for i in range(len(data)):
data[i] = camelize(data[i])
Tuples don’t support item assignment.
Suggested fix:
if isinstance(data, tuple):
data = list(data)
if isinstance(data, list):
for i in range(len(data)):
data[i] = camelize(data[i])
First of all, thanks for building this package. It's very convenient!
I recently updated to the latest release and noticed that rendering dict responses from DRF is broken. It looks like the iterator support added in #34 clobbers the original dict handling. The dict response is camelized correctly, but then the is_iterable(data)
conditional passes and immediately the dict is converted into a list of just the keys and that is what is returned.
I'm wondering if the intent was to make that an elif
conditional instead?
Uses:
/lib/python3.7/site-packages/djangorestframework_camel_case/util.py:23: RemovedInDjango40Warning: force_text() is deprecated in favor of force_str().
data = force_text(data)
settings.py
"JSON_UNDERSCOREIZE": {
# ...
"ignore_fields": ("order_update", ),
# ...
}
Still got output response:
{
"orderUpdate": {
"items": [
{
"parent": null,
"type": "tax",
"description": "Sales taxes",
"amount": 350,
"currency": "usd"
}
],
"shipping_methods": [
{
"id": "free_shipping",
"description": "Free 7-day shipping",
"amount": 0,
"currency": "usd",
"delivery_estimate": {
"type": "exact",
"date": "2020-08-11"
},
"tax_items": []
}
]
}
}
When I raise rest_framework.serializers.ValidationError({'some_field_name': 'some message'})
the resulting API response is {'some_field_name': [ErrorDetail(string='some message', code='invalid')]}
. The expected response would be {'someFieldName': [ErrorDetail(string='some message', code='invalid')]}
.
Substantial fixes like c25d707 are missing from actual PyPI package. Please update it.
e.g. {"ABCD": "1234"}
becomes {"a_bc_d": "1234"}
Hey, I like your package, unfortunately it reorders the field names in alphabetical order opposed to declaration order. Though computer don't mind I would prefer having the fields in declaration order.
Edit: Created a pull request.
can you generate a new version with Underscoreize feature? because the version installed by pip does not have this feature.
thank you!
In profiling a recent application, I noticed that camelize
added some load time.
Some other regexes are precomiled, so it seems like an oversight that the regex in camelize
is not also compiled.
eg:
camelize_re = re.compile(r"[a-z]_[a-z]")
...
new_key = camelize_re.sub(underscoreToCamel, key)
Hello,
first thank you for this module. :) Second, I found out it has problem if data in renderer are in form of a generator. Problem is in function camelize
. Instead of checking if instance is list or tuple it should check if instance is iterable. Could you please fix it?
I configured my django according to guide. The error occurs:
ImportError: Could not import 'rest_framework.renderers.UnicodeJSONRenderer' for API setting 'RENDERER_CLASS'. AttributeError: module 'rest_framework.renderers' has no attribute 'UnicodeJSONRenderer'.
Changing UnicodeJSONRenderer
to JSONRenderer
another error occurs:
ImportError: Could not import 'djangorestframework_camel_case.parser.CamelCaseFormParser' for API setting 'DEFAULT_PARSER_CLASSES'. ModuleNotFoundError: No module named 'six'.
When using rest_framework.filters.OrderingFilter
in a view, one can add a list of comma-separated field names to an "order" query parameter (see the docs). However, those lists are currently not affected by this package, making it incompatible with it out-of-the-box. I solved this, by extending the get_ordering
method of the OrderingFilter
class:
from rest_framework.filters import OrderingFilter
from djangorestframework_camel_case.util import camel_to_underscore
from djangorestframework_camel_case.settings import api_settings
class CamelCaseOrderingFilter(OrderingFilter):
def get_ordering(self, request, queryset, view):
params = request.query_params.get(self.ordering_param)
if params:
fields = [camel_to_underscore(field.strip(), **api_settings.JSON_UNDERSCOREIZE,)
for field in params.split(',')]
ordering = self.remove_invalid_fields(queryset, fields, view, request)
if ordering:
return ordering
return self.get_default_ordering(view)
Now there are other packages using field lists in query parameters. I am currently trying to add drf-flex-fields to my app and I haven't found a good way to customize it to use "underscoreize" the fields
and expand
lists in this case.
Has anyone else faced this problem and has a solution? Or is it maybe in the scope of this project to provide a solution for field lists in query parameters?
The key address_line_1
renders as AddressLine_1
. I expect it to be AddressLine1
. Is there a reason for this, or can we fix it?
The field keys in serializer.errors are not in camelCase.
For example: {'snake_case': [u'This field is mandatory.']}
CamelCaseJSONParser does not care about the field whose name ends with more than one digit like this:
I hope the following will occur:
My serializer has some fields as follows:
api/serializers.py
from rest_framework import serializers
class FooSerializer(serializers.Serializer):
key_1 = serializers.IntegerField()
key_10 = serializers.IntegerField()
another_key_1 = serializers.IntegerField()
another_key_10 = serializers.IntegerField()
When I posted the following JSON data to the API using the above serializer,
{
"key1": 1,
"key10": 2,
"anotherKey1": 3,
"anotherKey10": 4
}
I got the following error response with the status code 400:
{
"key10":[
"This field is required."
],
"anotherKey10":[
"This field is required."
]
}
Other prerequisites are as follows:
api/views.py
from rest_framework import status, views
from .serializers import FooSerializer
class FooAPIView(views.APIView):
def post(self, request, *args, **kwargs):
serializer = FooSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status.HTTP_200_OK)
mysite/urls.py
from django.urls import path
from api import views as api_view
urlpatterns = [
path('api/foo/', api_view.FooAPIView.as_view()),
]
mysite/settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
'DEFAULT_RENDERER_CLASSES': (
'djangorestframework_camel_case.render.CamelCaseJSONRenderer',
'rest_framework.renderers.JSONRenderer',
),
'DEFAULT_PARSER_CLASSES': (
'djangorestframework_camel_case.parser.CamelCaseJSONParser',
'rest_framework.parsers.JSONParser',
),
}
>pip list
Package Version
------------------------------ -------
Django 2.2.3
djangorestframework 3.9.4
djangorestframework-camel-case 1.0.3
CamelCaseJSONParser does not care about the pattern which ends with more than one digit.
The points that should be revised are as follows:
diff --git a/djangorestframework_camel_case/util.py b/djangorestframework_camel_case/util.py
index d8a62d1..5780ecf 100644
--- a/djangorestframework_camel_case/util.py
+++ b/djangorestframework_camel_case/util.py
@@ -42,7 +42,7 @@ def get_underscoreize_re(options):
if options.get("no_underscore_before_number"):
pattern = r"([a-z]|[0-9]+[a-z]?|[A-Z]?)([A-Z])"
else:
- pattern = r"([a-z]|[0-9]+[a-z]?|[A-Z]?)([A-Z0-9])"
+ pattern = r"([a-z]|[0-9]+[a-z]?|[A-Z]?)([A-Z]|[0-9]+)"
return re.compile(pattern)
diff --git a/tests.py b/tests.py
index 8fa7b0b..9c9acc6 100644
--- a/tests.py
+++ b/tests.py
@@ -58,6 +58,7 @@ class CamelToUnderscoreTestCase(TestCase):
"bOnlyOneLetter": 5,
"onlyCLetter": 6,
"mix123123aAndLetters": 7,
+ "underscoreBefore123": 8,
}
output = {
"two_word": 1,
@@ -67,6 +68,7 @@ class CamelToUnderscoreTestCase(TestCase):
"b_only_one_letter": 5,
"only_c_letter": 6,
"mix_123123a_and_letters": 7,
+ "underscore_before_123": 8,
}
self.assertEqual(underscoreize(data), output)
Hello all,
This was working fine until I started saving ForeignKeys. No matter the JSON property type (string / integer), it always stores null.
A
model:
class Streetlight(models.Model):
refStreetlightModel = models.ForeignKey(
'StreetlightModel', null=True, blank=True, on_delete=models.SET_NULL)
A
serializer:
class StreetlightSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Streetlight
fields = ('id', 'type', 'created', 'refStreetlightModel', 'url')
If I do remove
'DEFAULT_RENDERER_CLASSES': (
'djangorestframework_camel_case.render.CamelCaseJSONRenderer',
# Any other renders
),
'DEFAULT_PARSER_CLASSES': (
'djangorestframework_camel_case.parser.CamelCaseJSONParser',
# Any other parsers
),
from my settings, It all works as expected. When I POST
{
...
"refStreetlightModel": "/streetlightmodels/17/",
...
}
I do get the full url back when issuing a GET on this saved value. However, when using this parser and renderer, refStreetlightModel
field is always stored as null.
Am I doing something wrong? Any help would be much appreciated!
Cheers
Some time ago I looked at using this project for converting JSON responses from underscore case to camelcase but the problem I ran into is that it doesn't distinguish between keys that are values and keys that are field names
For example:
import djangorestframework_camel_case.util as util
data = {
'first_name': 'Mary',
'last_name': 'Smith',
'servers': {
'server_west.mycompany.com': '...',
'server_south.mycompany.com': '...',
},
}
print(json.dumps(util.camelize(data), indent=4))
Output is:
{
"firstName": "Mary",
"lastName": "Smith",
"servers": {
"serverWest.mycompany.com": "...",
"serverSouth.mycompany.com": "..."
}
}
There's no way of indicating that the keys in the servers
object shouldn't be modified because it's an associative array where the keys are user-supplied data.
I created an alternate implementation that adds an ignore
parameter, so eg you could do the following:
util.camelize(data, ignore=['servers'])
Anything in the tree that matches the ignore specifier will be ignored (it will still recurse into that node but won't change the case on the key, and also handles arrays; ignore=['servers', 'servers.*.user_accounts']
would allow you to correctly transform something like:
{
"first_name": "Mary",
"last_name": "Smith",
"servers": {
"server_west.mycompany.com": {
'user_accounts': {
'mary_smith': {
'home_dir': '/home/mary_smith',
},
},
},
},
}
into
{
"firstName": "Mary",
"lastName": "Smith",
"servers": {
"server_west.mycompany.com": {
'userAccounts': {
'mary_smith': {
'homeDir': '/home/mary_smith',
},
},
},
},
}
If I cleaned up the code is it something that you'd be interesting in accepting a PR for or outside the scope of this project?
I found weird underscorization.
>>> from djangorestframework_camel_case.util import camel_to_underscore
>>> camel_to_underscore('anotherKey10')
'another_key_10'
That's OK :)
>>> camel_to_underscore('anotherKey1')
'another_key1'
That's weird. I hope that it should return 'another_key_1'.
My requirements are as follows:
Django==2.2.6
djangorestframework==3.10.3
djangorestframework-camel-case==1.1.2
Right now if you use this package and DRF's OpenAPI schema generator, the fields don't end up camelized. I have kludged together a quick fix for this:
class CamelizingAutoSchema(AutoSchema):
def _map_serializer(self, serializer):
result = super()._map_serializer(serializer)
camelized_properties = {
camelize_str(field_name): schema
for field_name, schema in result["properties"].items()
}
new_result = {"type": "object", "properties": camelized_properties}
if "required" in result:
new_result["required"] = list(map(camelize_str, result["required"]))
return new_result
It works for me and it seems like a good fit for this project, but I thought I'd check in first before making a PR because I'm not sure if it's an amazing idea. It's very useful and works, but overriding a private API (_map_serializer()
) doesn't seem great, especially since DRF's schema generation is quite new and a bit of a moving target at the moment.
But if you'd like I can add some tests for this and submit a PR, but it might need some maintenance.
DRF 3.10 dropped support for Python 2. As such, it is no longer to import six from restframework.compat
When I upgrade the version of django rest framework to 3.10.0, the project cannot start up and raise this exception.
Exception in thread django-main-thread:
Traceback (most recent call last):
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/settings.py", line 177, in import_from_string
return import_string(val)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/utils/module_loading.py", line 17, in import_string
module = import_module(module_path)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/djangorestframework_camel_case/parser.py", line 12, in <module>
from rest_framework.parsers import six, FormParser
ImportError: cannot import name 'six' from 'rest_framework.parsers' (/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/parsers.py)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 54, in wrapper
fn(*args, **kwargs)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
self.check(display_num_errors=True)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/management/base.py", line 390, in check
include_deployment_checks=include_deployment_checks,
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/management/base.py", line 377, in _run_checks
return checks.run_checks(**kwargs)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/checks/registry.py", line 72, in run_checks
new_errors = check(app_configs=app_configs)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/checks/urls.py", line 13, in check_url_config
return check_resolver(resolver)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/core/checks/urls.py", line 23, in check_resolver
return check_method()
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/urls/resolvers.py", line 398, in check
for pattern in self.url_patterns:
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/utils/functional.py", line 80, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/urls/resolvers.py", line 579, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/utils/functional.py", line 80, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/urls/resolvers.py", line 572, in urlconf_module
return import_module(self.urlconf_name)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/xiaohe/Projects/parasite-python/para_latipay/urls.py", line 22, in <module>
path('web/', include('para_latipay.para_web.urls')),
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/django/urls/conf.py", line 34, in include
urlconf_module = import_module(urlconf_module)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/xiaohe/Projects/parasite-python/para_latipay/para_web/urls.py", line 3, in <module>
from para_latipay.para_web.report_utils.ato_report_view import get_ato_report
File "/Users/xiaohe/Projects/parasite-python/para_latipay/para_web/report_utils/ato_report_view.py", line 7, in <module>
from rest_framework.decorators import api_view, permission_classes
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/decorators.py", line 13, in <module>
from rest_framework.views import APIView
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/views.py", line 104, in <module>
class APIView(View):
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/views.py", line 108, in APIView
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/settings.py", line 220, in __getattr__
val = perform_import(val, attr)
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/settings.py", line 168, in perform_import
return [import_from_string(item, setting_name) for item in val]
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/settings.py", line 168, in <listcomp>
return [import_from_string(item, setting_name) for item in val]
File "/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/settings.py", line 180, in import_from_string
raise ImportError(msg)
ImportError: Could not import 'djangorestframework_camel_case.parser.CamelCaseJSONParser' for API setting 'DEFAULT_PARSER_CLASSES'. ImportError: cannot import name 'six' from 'rest_framework.parsers' (/Users/xiaohe/Projects/parasite-python/venv/lib/python3.7/site-packages/rest_framework/parsers.py).
I'm using djangorestframework-camel-case
,
but It is a little inconvenient because I can not use html renderer.
So I created a calmel case html renderer using drf's defualt html renderer.
Hi! Is there a way to apply the renderer class to a specific APIWiev instance? I have already so many endpoints created that do not return camelCase keys so putting the renderer method as a default render will break existing things. So I tried setting it up like this but that did not work for me:
from djangorestframework_camel_case.render import CamelCaseJSONRenderer
class ActiveSubscriptionsAPIView(CamelCaseJSONRenderer, APIView):
stuff
Thanks in advance!
Is there any option to underscoreize GET params with this package? If not what is the best option to do that, add custom middleware?
Looks like it will work for the top level keys in a json data structure, but does it work for nested data like this? Does not seems to work for nestedKey
in the scenario below.
{
someKey1: "value 1"
someKey2: "value 2"
someKey3: [{"nestedKey":"nested value"}]
}
Using it with a tuple data raise the following exception 'tuple' object does not support item assignment
.
Perhaps it should cast tuples to list before that, I'll try to create a patch.
Hi folks, in my API I have some keys with _leading_underscores
, for example:
{
'_str': 'String',
'_timestamp': 1234567890,
'firstValue': '...',
'secondValue: '...'
}
I want to preserve these leading _
's, but camelize the other fields.
I am thinking about a PR that adds a setting PRESERVE_LEADING_UNDERSCORE
, which would allow camelize_re
in utils.py
to be [a-z0-9]_[a-z0-9]
instead of [a-z0-9]?_[a-z0-9]
- note the changed '?'.
This would probably involve changing camelize_re
from being a constant to being generated by a utils.py
function, perhaps get_camelize_re()
.
Thoughts?
I am using restframework 3.11.0, camel case 1.1.2 and unfortunately it doesn't seem to work for Multipart files when I add MultipartParser
like below
class JobPostViewSet(viewsets.ModelViewSet):
parser_classes = (parsers.MultiPartParser,)
I have to send the data in snake case for my api to work when I am using MultipartParser
Hello all,
I've been using this renderer and parser with DRF 3.0 and while it has been working great, I had to ditch it now that I also need to use serializers from rest_framework_gis, particularly the GeoModelSerializer
.
Here is a JSON example I'm POSTing:
{
"id": "streetlight:guadalajara:4567",
"type": "Streetlight",
"location": {
"type": "Point",
"coordinates": [ -3.164485591715449, 40.62785133667262 ]
}
}
and here is my serializer:
class StreetlightSerializer(gis_serializers.GeoModelSerializer):
class Meta:
model = Streetlight
fields = ('id', 'type', 'created', 'location', 'ref_streetlight_model',
'url', 'ref_streetlight_group', 'ref_streetlight_control_cabinet')
geo_field = 'location'
and model:
class Streetlight(models.Model):
...
location = PointField(
srid=4326, blank=True, null=True
)
When using this lib as rest_framework's default render and parser, I get the following traceback https://pastebin.com/nxNwhE7T
Is there any easy clean to get past this, without manually invoking the parser / renderer at the right time (before the serializer) ?
Thanks!
EDIT
Actually, this happens when my serializer is also set to serializers.ModelSerializer
- so I guess I'll have to take care of this location
field (GeoJSON) manually in my serializer, right?
Hi there! Very nice tool, thanks!
Would this this library also work with Django's JsonResponse
?
According to Django's doc:
https://docs.djangoproject.com/en/2.0/ref/request-response/#jsonresponse-objects
an encoder can be set.
response = JsonResponse(data, encoder=MyJSONEncoder)
For example, in views.py
:
from django.http import JsonResponse
from .models import User
from .serializers import UserSerializer
def user_view(request):
user = User.objects.get(pk=1)
return JsonResponse(UserSerializer(user).data, encoder=CamelCaseJSONEncoder)
That'd be pretty elegant... ;)
throws TypeError: expected string or bytes-like object.
I'm guessing we should gracefully handle and ignore keys that are not string (such as integer), rather than force them to be string.
Please start making Change Log / using GitHub Releases, so it's possible to know what was changed (like #50)
This does not appear to work with DRF 3.0 on POST or PUTs. It renders fine, but does not work when camel cased fields are passed to create or update items.
I'm definitely using the camel_to_underscore function in an unexpected way (I'm transforming values as well as keys in some cases), but I think you'll agree this is bad behavior:
from djangorestframework_camel_case.util import camel_to_underscore
camel_to_underscore("one Two")
>>> 'one _Two'
The first_cap_re regexp is a little naive. I'm not sure what the exact fix is, but there you go.
Fix is in util.camelize method:
Instead of this:
new_key = re.sub(r"[a-z]_[a-z]", underscoreToCamel, key)
Do this:
new_key = isinstance(key, basestring) and re.sub(r"[a-z]_[a-z]", underscoreToCamel, key) or key
It would be useful to have a way to let an object be rendered without transformation.
Suggestion: add a marker class used like return Response({'valid_values': nocamel(some_choices)})
and change the camelize function to not change these objects. The result here would be {"validValues": [["thing_one", "Thing one"], ["thing_two", "Thing two"]]}
.
For sure, a variable named accepted_TOS
isn't ideal. At the same time, it's a valid python variable name, yet this library wouldn't work with it.
When trying to consume my api, I tried the following:
acceptedTOS
acceptedTos
accepted_TOS
acceptedtos
acceptedT
acceptedt
All invalid. As soon as I disabled this package and tried it with the python style variable names it worked.
So something is being bungled within this package, given the way it mishandles that variable.
See here for reference. I ultimately went and changed the variable name to something more pythonic, but in my opinion the old name ought to work as it is a valid python variable or model field name.
My DRF project is under the following conditions.
>pip list
Package Version
------------------------------ -----------
Django 2.2.3
...
djangorestframework 3.10.0
djangorestframework-camel-case 1.0.3
...
six 1.12.0
REST_FRAMEWORK = {
...
'DEFAULT_PARSER_CLASSES': (
'djangorestframework_camel_case.parser.CamelCaseJSONParser',
'rest_framework.parsers.JSONParser',
),
...
}
This raises the following error while starting up runserver.
...
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\generics.py", line 9, in <module>
from rest_framework import mixins, views
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\views.py", line 104, in <module>
class APIView(View):
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\views.py", line 108, in APIView
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\settings.py", line 220, in __getattr__
val = perform_import(val, attr)
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\settings.py", line 168, in perform_import
return [import_from_string(item, setting_name) for item in val]
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\settings.py", line 168, in <listcomp>
return [import_from_string(item, setting_name) for item in val]
File "C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\settings.py", line 180, in import_from_string
raise ImportError(msg)
ImportError: Could not import 'djangorestframework_camel_case.parser.CamelCaseJSONParser' for API setting 'DEFAULT_PARSER_CLASSES'. ImportError: cannot import name 'six' from 'rest_framework.parsers' (C:\Users\akiyoko\PycharmProjects\myproject\venv\lib\site-packages\rest_framework\parsers.py).
This error seems caused by the compatibility between [email protected] and [email protected].
DRF 3.10 release dropped support for Python 2 and rest_framework/[email protected] removed the import of six, but djangorestframework_camel_case/parser.py needs rest_framework.parsers.six.
This is the first part of djangorestframework_camel_case/parser.py@master.
...
import six
...
from rest_framework.parsers import six, FormParser
Now, I tried to fix djangorestframework_camel_case/parser.py as follows, it works perfectly.
...
import six
...
from rest_framework.parsers import FormParser
Snake case values such as
need_i_know
is converted to
needI_know
in Camel Case. It should have been
needIKnow
. Please find a solution for this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.