diff --git a/gas/templatetags/form_tags.py b/gas/templatetags/form_tags.py index a17ac69..a0d8853 100644 --- a/gas/templatetags/form_tags.py +++ b/gas/templatetags/form_tags.py @@ -1,8 +1,6 @@ from django import forms from django import template -from django.conf import settings from django.template.loader import render_to_string -from django.urls import reverse register = template.Library() @@ -11,7 +9,6 @@ def base_form_field(field, css=None, container_class='', add_another_url=None, f if field.is_hidden: return str(field) - classes = field.field.widget.attrs.get('class', '').split(' ') classes.append('form-control') if css: diff --git a/gas/tests/test_utils.py b/gas/tests/test_utils.py new file mode 100644 index 0000000..5ee9bc7 --- /dev/null +++ b/gas/tests/test_utils.py @@ -0,0 +1,46 @@ +import datetime +import json + +from django.test import TestCase +from django.contrib.auth.models import User +from django.utils.translation import gettext_lazy as _ + +from model_bakery import baker + +from gas import utils + + +class UtilsTestCase(TestCase): + def test_jsonencoder(self): + users = baker.make('auth.User', _quantity=3) + now = datetime.datetime.now() + today = datetime.date.today() + data = { + 'now': now, + 'today': today, + 'users': User.objects.all().values_list('pk', flat=True), + 'lazy_string': _('lazy'), + } + + dumped_data = json.dumps(data, cls=utils.JSONEncoder) + recovered_data = json.loads(dumped_data) + + self.assertEqual( + recovered_data['now'], + now.strftime('%Y-%m-%d %H:%M') + ) + self.assertEqual( + recovered_data['today'], + today.strftime('%Y-%m-%d') + ) + self.assertEqual( + len(recovered_data['users']), + 3, + ) + self.assertEqual( + set(recovered_data['users']), + set(user.pk for user in users), + ) + self.assertEqual( + recovered_data['lazy_string'], 'lazy', + ) diff --git a/gas/tests/test_views.py b/gas/tests/test_views.py index eb9c867..068e68a 100644 --- a/gas/tests/test_views.py +++ b/gas/tests/test_views.py @@ -1,4 +1,5 @@ import json +import datetime from django import forms from django.contrib.auth.models import User @@ -68,6 +69,34 @@ class AjaxCommandTestCase(TestCase): response = post_view(request) self.assertEqual(response.status_code, 200) + def test_custom_json_encoder(self): + class CustomEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime): + return 'datetime' + if isinstance(obj, datetime.date): + return 'date' + return json.JSONEncoder.default(self, obj) + + class SampleAjaxView(gviews.AjaxCommandsMixin, View): + def do_test(self): + return self.render_json({ + 'now': datetime.datetime.now(), + 'today': datetime.date.today(), + }, encoder=CustomEncoder) + + view = SampleAjaxView.as_view() + request_factory = RequestFactory() + + # Command with corresponding "do_" method + request = request_factory.post('some_url', { + 'command': 'test', + }) + response = view(request) + data = json.loads(response.content) + self.assertEqual(data['now'], 'datetime') + self.assertEqual(data['today'], 'date') + class GASMixinTestCase(TestCase): def setUp(self): diff --git a/gas/utils.py b/gas/utils.py new file mode 100644 index 0000000..96292fc --- /dev/null +++ b/gas/utils.py @@ -0,0 +1,18 @@ +import datetime +import json + +from django.db.models import QuerySet +from django.utils.functional import Promise + + +class JSONEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime): + return obj.strftime('%Y-%m-%d %H:%M') + if isinstance(obj, datetime.date): + return obj.strftime('%Y-%m-%d') + if isinstance(obj, QuerySet): + return list(obj) + if isinstance(obj, Promise): + return str(obj) + return json.JSONEncoder.default(self, obj) diff --git a/gas/views.py b/gas/views.py index be08d8c..b96dd11 100644 --- a/gas/views.py +++ b/gas/views.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import ListView, CreateView, UpdateView, DeleteView from . import gas_settings +from . import utils class AjaxCommandsMixin: @@ -27,8 +28,10 @@ class AjaxCommandsMixin: handler = getattr(super(), 'post', self.http_method_not_allowed) return handler(request, *args, **kwargs) - def render_json(self, data): - return HttpResponse(json.dumps(data), content_type='application/json') + def render_json(self, data, encoder=utils.JSONEncoder): + return HttpResponse( + json.dumps(data, indent=2, cls=encoder), + content_type='application/json') class GASMixin: