Skip to content

Commit

Permalink
Merge pull request #6 from igorkramaric/django-1.9
Browse files Browse the repository at this point in the history
Django 1.9
  • Loading branch information
jiaaro committed Dec 30, 2015
2 parents 973c059 + 7ae8cc8 commit 5e08fd4
Show file tree
Hide file tree
Showing 18 changed files with 326 additions and 72 deletions.
32 changes: 17 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,40 @@ env:
global:
- DJANGO_SETTINGS_MODULE=test_project.settings
matrix:
- DJANGO=1.4
- DJANGO=1.5
- DJANGO=1.6
- DJANGO=1.7
- DJANGO=1.8
- DJANGO=1.9
matrix:
exclude:
- python: "3.2"
env: DJANGO=1.4
env: DJANGO=1.7
- python: "3.3"
env: DJANGO=1.4
- python: "3.4"
env: DJANGO=1.4
- python: "3.4"
env: DJANGO=1.5
env: DJANGO=1.7
- python: "3.4"
env: DJANGO=1.6
- python: "2.6"
env: DJANGO=1.7
- python: "2.6"
env: DJANGO=dev
- python: "3.5"
env: DJANGO=1.7
- python: "3.4"
env: DJANGO=1.8
- python: "3.5"
env: DJANGO=1.8
allow_failures:
- python: "3.2"
- python: "3.3"
- python: "3.4"
- python: "3.5"
install:
- pip install django==${DJANGO} Pillow
- pip install django==${DJANGO} Pillow psycopg2
- pip install .
addons:
postgresql: "9.3"
before_script:
- psql -c 'create database test_jsonate;' -U postgres
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "3.5"
script: python test_project/manage.py test test_app
5 changes: 3 additions & 2 deletions jsonate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from jsonate.utils import jsonate
from . import monkey_patches
from .utils import jsonate

default_app_config = 'jsonate.apps.JsonateAppConfig'
8 changes: 8 additions & 0 deletions jsonate/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig

class JsonateAppConfig(AppConfig):
name = 'jsonate'

def ready(self):
# from . import monkey_patches
pass
3 changes: 3 additions & 0 deletions jsonate/django_ver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import django
django_19 = (django.VERSION >= (1,9))
django_18 = (django.VERSION >= (1,8))
41 changes: 25 additions & 16 deletions jsonate/fields.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
from django.db import models
try:
import json
except ImportError:
from django.utils import simplejson as json
from jsonate.utils import jsonate
from jsonate.widgets import JsonateWidget
from jsonate.form_fields import JsonateFormField

from django.db import models

from .utils import jsonate
from .django_ver import django_19
from .widgets import JsonateWidget
from .form_fields import JsonateFormField

class JsonateField(models.TextField):
__metaclass__ = models.SubfieldBase
if not django_19:
__metaclass__ = models.SubfieldBase

def to_python(self, value):
def _deserialize(self, value):
if value == "":
return None

Expand All @@ -19,24 +23,29 @@ def to_python(self, value):
return json.loads(value)
except ValueError:
pass

return value

def get_db_prep_save(self, value, *args, **kwargs):
def from_db_value(self, value, expression, connection, context):
return self._deserialize(value)

def to_python(self, value):
return self._deserialize(value)

def get_db_prep_value(self, value, connection, prepared=False):
if value == "":
return None
value = jsonate(value)
return super(JsonateField, self).get_db_prep_save(value, *args, **kwargs)


if not isinstance(value, basestring):
value = jsonate(value)

return value

def formfield(self, **kwargs):
defaults = {
'form_class': JsonateFormField,
'widget': JsonateWidget
}
defaults.update(kwargs)
return super(JsonateField, self).formfield(**defaults)

try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^jsonate\.fields\.JsonateField"])
except ImportError:
pass
return super(JsonateField, self).formfield(**defaults)
8 changes: 5 additions & 3 deletions jsonate/form_fields.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from django.forms import CharField, ValidationError
from jsonate.widgets import JsonateWidget
try:
import json
except ImportError:
from django.utils import simplejson as json


from django.forms import CharField, ValidationError

from .widgets import JsonateWidget


def JsonateValidator(value):
try:
json.loads(value)
Expand Down
41 changes: 30 additions & 11 deletions jsonate/json_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@
import json
except ImportError:
from django.utils import simplejson as json
from django.db.models.query import QuerySet, ValuesQuerySet

from .django_ver import django_19
if django_19:
from django.db.models.query import ModelIterable
else:
from django.db.models.query import ValuesQuerySet

from django.db.models.query import QuerySet
from django.db.models import Model
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.files import FieldFile

from jsonate.exceptions import CouldntSerialize
from .exceptions import CouldntSerialize

# Custom encoder using a list of mapping functions
type_map = []
Expand Down Expand Up @@ -63,22 +70,34 @@ def map_object(obj):
if to_json is None:
raise CouldntSerialize
return to_json()

# Must come before map_queryset because ValuesQuerySet is
# a subclass of Queryset and will cause an infinite loop :(
@register_typemap(ValuesQuerySet)
def map_values_queryset(obj):
return list(obj)


if not django_19:
# Must come before map_queryset because ValuesQuerySet is
# a subclass of Queryset and will cause an infinite loop :(
@register_typemap(ValuesQuerySet)
def map_values_queryset(obj):
return list(obj)

@register_typemap(QuerySet)
def map_queryset(obj):
# if the model wants to serialize itself, go with that...
if hasattr(obj.model, 'to_json') or hasattr(obj.model, 'toJSON'):
return list(obj)

# otherwise using values is faster
fields = jsonate_fields(obj.model)
return obj.values(*[field.name for field in fields])
if django_19:
if obj._iterable_class == ModelIterable:

fields = jsonate_fields(obj.model)
obj = obj.values(*[field.name for field in fields])

return list(obj)

else:
fields = jsonate_fields(obj.model)
return obj.values(*[field.name for field in fields])


@register_typemap(Model)
def map_model_instance(obj):
Expand Down
4 changes: 2 additions & 2 deletions jsonate/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import json
except ImportError:
from django.utils import simplejson as json
from jsonate.json_encoder import JsonateEncoder

from .json_encoder import JsonateEncoder

def jsonate(obj, *args, **kwargs):
kwargs['cls'] = JsonateEncoder
Expand Down
7 changes: 5 additions & 2 deletions jsonate/widgets.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from django import forms
try:
import json
except ImportError:
from django.utils import simplejson as json
from jsonate.utils import jsonate

from django import forms

from .utils import jsonate


class JsonateWidget(forms.Textarea):

Expand Down
5 changes: 5 additions & 0 deletions test_project/manage.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
#!/usr/bin/env python
import os

try:
import settings # Assumed to be in the same directory.

except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")

try:
from django.core.management import execute_from_command_line
execute_from_command_line()

except ImportError:
from django.core.management import execute_manager
execute_manager(settings)
7 changes: 5 additions & 2 deletions test_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_jsonate'
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'test_jsonate',
'USER': 'postgres'
}
}

Expand All @@ -23,6 +24,8 @@
os.path.join(PROJECT_ROOT, 'templates'),
)

SECRET_KEY = "dna_kzxq8(QbM=-#ZyyA&k,Fi1LU>&bQ4ZA+|(e<g-.%L0JnaK"

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
Expand Down
37 changes: 37 additions & 0 deletions test_project/test_app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2015-12-15 14:16
from __future__ import unicode_literals

import datetime
from decimal import Decimal
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='MyModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('normal_field1', models.CharField(default=b'field1', max_length=25)),
('normal_field2', models.CharField(default=b'field2', max_length=25)),
('sensitive_field1', models.CharField(default=b'sensitive', max_length=25)),
('datetime_field', models.DateTimeField(default=datetime.datetime(2011, 1, 11, 11, 11, 11))),
('date_field', models.DateField(default=datetime.date(2011, 1, 11))),
('decimal_field', models.DecimalField(decimal_places=2, default=Decimal('32.25'), max_digits=10)),
('float_field', models.FloatField(default=32.25)),
('file_field', models.FileField(upload_to=b'files')),
('image_field', models.ImageField(upload_to=b'images')),
('boolean_field', models.BooleanField(default=True)),
('null_field', models.NullBooleanField(default=None)),
('foreign_key', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
23 changes: 23 additions & 0 deletions test_project/test_app/migrations/0002_mymodelwithjsonatefield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import jsonate.fields


class Migration(migrations.Migration):

dependencies = [
('test_app', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='MyModelWithJsonateField',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('some_name', models.CharField(max_length=255)),
('some_json_data', jsonate.fields.JsonateField(null=True, blank=True)),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import jsonate.fields
import test_app.models

class Migration(migrations.Migration):

dependencies = [
('test_app', '0002_mymodelwithjsonatefield'),
]

operations = [
migrations.CreateModel(
name='WithJsonateFieldExpectingList',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('some_name', models.CharField(max_length=255)),
('some_json_data', jsonate.fields.JsonateField(default=list, validators=[test_app.models.validate_list])),
],
),
]
Empty file.
Loading

0 comments on commit 5e08fd4

Please sign in to comment.