Skip to content

Commit

Permalink
Add Django 1.9 support (ref #349).
Browse files Browse the repository at this point in the history
  • Loading branch information
zlorf committed Dec 6, 2015
1 parent 1986e1a commit 8320fc8
Show file tree
Hide file tree
Showing 10 changed files with 300 additions and 90 deletions.
44 changes: 44 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ python:
- "3.2"
- "3.3"
- "3.4"
- "3.5"
env:
- DJANGO=1.4 DB=sqlite
- DJANGO=1.4 DB=postgres
Expand All @@ -21,6 +22,9 @@ env:
- DJANGO=1.8 DB=sqlite
- DJANGO=1.8 DB=postgres
- DJANGO=1.8 DB=mysql
- DJANGO=1.9 DB=sqlite
- DJANGO=1.9 DB=postgres
- DJANGO=1.9 DB=mysql
matrix:
exclude:
- python: "3.2"
Expand All @@ -41,6 +45,12 @@ matrix:
env: DJANGO=1.4 DB=postgres
- python: "3.4"
env: DJANGO=1.4 DB=mysql
- python: "3.5"
env: DJANGO=1.4 DB=sqlite
- python: "3.5"
env: DJANGO=1.4 DB=postgres
- python: "3.5"
env: DJANGO=1.4 DB=mysql

- python: "2.6"
env: DJANGO=1.7 DB=sqlite
Expand All @@ -54,31 +64,65 @@ matrix:
env: DJANGO=1.8 DB=postgres
- python: "2.6"
env: DJANGO=1.8 DB=mysql
- python: "2.6"
env: DJANGO=1.9 DB=sqlite
- python: "2.6"
env: DJANGO=1.9 DB=postgres
- python: "2.6"
env: DJANGO=1.9 DB=mysql
- python: "3.2"
env: DJANGO=1.9 DB=sqlite
- python: "3.2"
env: DJANGO=1.9 DB=postgres
- python: "3.2"
env: DJANGO=1.9 DB=mysql
- python: "3.3"
env: DJANGO=1.9 DB=sqlite
- python: "3.3"
env: DJANGO=1.9 DB=postgres
- python: "3.3"
env: DJANGO=1.9 DB=mysql

- python: "3.2"
env: DJANGO=1.5 DB=mysql
- python: "3.3"
env: DJANGO=1.5 DB=mysql
- python: "3.4"
env: DJANGO=1.5 DB=mysql
- python: "3.5"
env: DJANGO=1.5 DB=mysql
- python: "3.2"
env: DJANGO=1.6 DB=mysql
- python: "3.3"
env: DJANGO=1.6 DB=mysql
- python: "3.4"
env: DJANGO=1.6 DB=mysql
- python: "3.5"
env: DJANGO=1.6 DB=mysql
- python: "3.2"
env: DJANGO=1.7 DB=mysql
- python: "3.3"
env: DJANGO=1.7 DB=mysql
- python: "3.4"
env: DJANGO=1.7 DB=mysql
- python: "3.5"
env: DJANGO=1.7 DB=mysql
- python: "3.2"
env: DJANGO=1.8 DB=mysql
- python: "3.3"
env: DJANGO=1.8 DB=mysql
- python: "3.4"
env: DJANGO=1.8 DB=mysql
- python: "3.5"
env: DJANGO=1.8 DB=mysql
- python: "3.2"
env: DJANGO=1.9 DB=mysql
- python: "3.3"
env: DJANGO=1.9 DB=mysql
- python: "3.4"
env: DJANGO=1.9 DB=mysql
- python: "3.5"
env: DJANGO=1.9 DB=mysql
before_install:
- pip install -q flake8 --use-mirrors
- PYFLAKES_NODOCTEST=1 flake8 modeltranslation
Expand Down
20 changes: 19 additions & 1 deletion modeltranslation/fields.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from django import VERSION
from django import forms
from django.core.exceptions import ImproperlyConfigured
from django.db.models import fields
Expand Down Expand Up @@ -33,6 +34,8 @@
# Above implies also OneToOneField
)

NEW_RELATED_API = VERSION >= (1, 9)


class NONE:
"""
Expand Down Expand Up @@ -150,7 +153,7 @@ def __init__(self, translated_field, language, empty_value, *args, **kwargs):
self.verbose_name = build_localized_verbose_name(translated_field.verbose_name, language)

# ForeignKey support - rewrite related_name
if self.rel and self.related and not self.rel.is_hidden():
if not NEW_RELATED_API and self.rel and self.related and not self.rel.is_hidden():
import copy
current = self.related.get_accessor_name()
self.rel = copy.copy(self.rel) # Since fields cannot share the same rel object.
Expand All @@ -166,6 +169,21 @@ def __init__(self, translated_field, language, empty_value, *args, **kwargs):
self.rel.field = self # Django 1.6
if hasattr(self.rel.to._meta, '_related_objects_cache'):
del self.rel.to._meta._related_objects_cache
elif NEW_RELATED_API and self.remote_field and not self.remote_field.is_hidden():
import copy
current = self.remote_field.get_accessor_name()
# Since fields cannot share the same rel object:
self.remote_field = copy.copy(self.remote_field)

if self.remote_field.related_name is None:
# For implicit related_name use different query field name
loc_related_query_name = build_localized_fieldname(
self.related_query_name(), self.language)
self.related_query_name = lambda: loc_related_query_name
self.remote_field.related_name = build_localized_fieldname(current, self.language)
self.remote_field.field = self # Django 1.6
if hasattr(self.remote_field.to._meta, '_related_objects_cache'):
del self.remote_field.to._meta._related_objects_cache

# Django 1.5 changed definition of __hash__ for fields to be fine with hash requirements.
# It spoiled our machinery, since TranslationField has the same creation_counter as its
Expand Down
9 changes: 8 additions & 1 deletion modeltranslation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ def to_python(self, value):

# Django 1.6
def _has_changed(self, initial, data):
return self.has_changed(initial, data)

def has_changed(self, initial, data):
if (initial is None and data is not None) or (initial is not None and data is None):
return True
return super(NullableField, self)._has_changed(initial, data)
obj = super(NullableField, self)
if hasattr(obj, 'has_changed'):
return obj.has_changed(initial, data)
else: # Django < 1.9 compat
return obj._has_changed(initial, data)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"""
from optparse import make_option
import django
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
from django.core.management.color import no_style
from django.db import connection, transaction
from django.utils.six import moves
Expand Down Expand Up @@ -46,17 +46,17 @@ def print_missing_langs(missing_langs, field_name, model_name):
field_name, model_name, ", ".join(missing_langs)))


class Command(NoArgsCommand):
class Command(BaseCommand):
help = ('Detect new translatable fields or new available languages and'
' sync database structure. Does not remove columns of removed'
' languages or undeclared fields.')

option_list = NoArgsCommand.option_list + (
option_list = BaseCommand.option_list + (
make_option('--noinput', action='store_false', dest='interactive', default=True,
help='Do NOT prompt the user for input of any kind.'),
)

def handle_noargs(self, **options):
def handle(self, *args, **options):
"""
Command execution.
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
from django.db.models import F, Q
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand

from modeltranslation.settings import DEFAULT_LANGUAGE
from modeltranslation.translator import translator
from modeltranslation.utils import build_localized_fieldname


class Command(NoArgsCommand):
class Command(BaseCommand):
help = ('Updates empty values of default translation fields using'
' values from original fields (in all translated models).')

def handle_noargs(self, **options):
def handle(self, *args, **options):
verbosity = int(options['verbosity'])
if verbosity > 0:
self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE)
Expand Down

0 comments on commit 8320fc8

Please sign in to comment.