mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-26 21:14:01 +00:00
Changed handling of supported fields. By default CharField, TextField and subclasses of these fields are supported. Supported fields can be extended through the setting MODELTRANSLATION_CUSTOM_FIELDS. Support for related fields is experimental and these fields explicitly raise a FutureWarning now.
This commit is contained in:
parent
6438ef28e5
commit
63fd7c0c7c
5 changed files with 54 additions and 34 deletions
|
|
@ -11,6 +11,7 @@
|
|||
ManyToManyField and OneToOneField.
|
||||
(resolves issue 15)
|
||||
|
||||
CHANGED: Custom fields are extended instead of overridden.
|
||||
CHANGED: Factored out settings into a separate settings.py and consistently
|
||||
used an app specific settings prefix.
|
||||
CHANGED: Refactored creation of translation fields and added handling of
|
||||
|
|
|
|||
|
|
@ -303,6 +303,24 @@ the ``django.utils.i18n.get_language`` function to determine the current
|
|||
language.
|
||||
|
||||
|
||||
Supported fields
|
||||
----------------
|
||||
``Modeltranslation`` officially supports CharField and TextField.
|
||||
|
||||
*New in development version*
|
||||
In most cases subclasses of these fields will work fine, too. Other fields
|
||||
aren't supported and will throw an ``ImproperlyConfigured`` exception.
|
||||
|
||||
The list of supported fields can be extended. Just define a tuple of field names in your settings.py like this::
|
||||
|
||||
MODELTRANSLATION_CUSTOM_FIELDS = ('MyField', 'MyOtherField',)
|
||||
|
||||
*Note:* This just prevents ``modeltranslation`` from throwing an
|
||||
``ImproperlyConfigured`` exception. Any non text-like field will most likely
|
||||
fail in one way or another. The feature is considered experimental and might be
|
||||
replaced by a more sophisticated mechanism in future versions.
|
||||
|
||||
|
||||
Set a default value
|
||||
-------------------
|
||||
*New in development version*
|
||||
|
|
@ -334,8 +352,8 @@ following:
|
|||
1. Removes the original field from every admin form by setting it
|
||||
``editable=False``.
|
||||
2. Copies the widget of the original field to each of it's translation fields.
|
||||
3. Checks if the - now removed - original field was required and if so makes the
|
||||
default translation field required instead.
|
||||
3. Checks if the - now removed - original field was required and if so makes
|
||||
the default translation field required instead.
|
||||
|
||||
|
||||
TranslationAdmin in combination with other admin classes
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from warnings import warn
|
|||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.models.fields import Field, CharField
|
||||
from django.db.models.fields import Field, CharField, TextField
|
||||
from django.db.models.fields.related import (ForeignKey, OneToOneField,
|
||||
ManyToManyField)
|
||||
|
||||
|
|
@ -16,20 +16,28 @@ from modeltranslation.utils import (get_language,
|
|||
|
||||
def create_translation_field(model, field_name, lang):
|
||||
"""
|
||||
Translation field factory.
|
||||
Translation field factory. Returns a ``TranslationField`` based on a
|
||||
fieldname and a language.
|
||||
|
||||
Tries to create an object in the form ``'Translation%s' % cls_name``
|
||||
(e.g. ``TranslationForeignKey``, ``TranslationManyToManyField``) based on
|
||||
``model`` and ``field_name``. The class is usually a subclass of
|
||||
``TranslationField`` and is supposed to be implemented in this module. If
|
||||
the class is listed in ``STD_TRANSLATION_FIELDS`` then ``TranslationField``
|
||||
will be used to instantiate the object. If the class is neither implemented
|
||||
nor in ``STD_TRANSLATION_FIELDS`` ``ImproperlyConfigured`` will be raised.
|
||||
``TranslationField`` and is supposed to be implemented in this module.
|
||||
|
||||
The list of supported fields can be extended. Just define a tuple of field
|
||||
names in your settings.py like this::
|
||||
|
||||
MODELTRANSLATION_CUSTOM_FIELDS = ('MyField', 'MyOtherField',)
|
||||
|
||||
If the class is a subclass of CharField or TextField then the standard
|
||||
``TranslationField`` will be used to instantiate the object. If the class
|
||||
is neither a subclass of CharField or TextField, nor implemented here, nor
|
||||
in ``CUSTOM_FIELDS`` an ``ImproperlyConfigured`` exception will be raised.
|
||||
"""
|
||||
field = model._meta.get_field(field_name)
|
||||
cls_name = field.__class__.__name__
|
||||
# No subclass required for text fields
|
||||
if cls_name in STD_TRANSLATION_FIELDS:
|
||||
# No subclass required for text-like fields
|
||||
if isinstance(field, (CharField, TextField)) or cls_name in CUSTOM_FIELDS:
|
||||
return TranslationField(translated_field=field, language=lang)
|
||||
# Try to instantiate translation field subclass
|
||||
try:
|
||||
|
|
@ -41,11 +49,11 @@ def create_translation_field(model, field_name, lang):
|
|||
# Handle related fields
|
||||
if cls_name in ('ForeignKey', 'OneToOneField', 'ManyToManyField'):
|
||||
warn('Support for related fields is experimental and known to has '
|
||||
'flaws. Only use it if you know what you are doing.', UserWarning)
|
||||
to = field.rel.to._meta.object_name
|
||||
return translation_field(translated_field=field, language=lang, to=to)
|
||||
# TODO: Should never be reached?
|
||||
return TranslationField(field, lang)
|
||||
'flaws. Only use it if you know what you are doing.',
|
||||
FutureWarning)
|
||||
return translation_field(translated_field=field, language=lang,
|
||||
to=field.rel.to._meta.object_name)
|
||||
return TranslationField(translated_field=field, language=lang)
|
||||
|
||||
|
||||
class TranslationField(Field):
|
||||
|
|
|
|||
|
|
@ -26,20 +26,13 @@ if DEFAULT_LANGUAGE and DEFAULT_LANGUAGE not in AVAILABLE_LANGUAGES:
|
|||
elif not DEFAULT_LANGUAGE:
|
||||
DEFAULT_LANGUAGE = AVAILABLE_LANGUAGES[0]
|
||||
|
||||
# Only override this setting if you know what you are doing! It merely exist
|
||||
# to test currently unsupported fields.
|
||||
# FIXME: We can't seem to override this particular setting in tests.py
|
||||
STD_TRANSLATION_FIELDS =\
|
||||
getattr(settings, 'MODELTRANSLATION_STD_TRANSLATION_FIELDS',
|
||||
('CharField', 'TextField', 'URLField', 'EmailField', 'XMLField',))
|
||||
#try:
|
||||
#if sys.argv[1] == 'test':
|
||||
#STD_TRANSLATION_FIELDS =\
|
||||
#getattr(settings, 'MODELTRANSLATION_STD_TRANSLATION_FIELDS',
|
||||
#('CharField', 'TextField', 'URLField', 'EmailField',
|
||||
#'XMLField', 'BooleanField', 'NullBooleanField',
|
||||
#'IntegerField', 'BigIntegerField', 'PositiveIntegerField',
|
||||
#'PositiveSmallIntegerField', 'SmallIntegerField',
|
||||
#'CommaSeparatedIntegerField'))
|
||||
#except IndexError:
|
||||
#pass
|
||||
CUSTOM_FIELDS =\
|
||||
getattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS', ())
|
||||
try:
|
||||
if sys.argv[1] == 'test':
|
||||
CUSTOM_FIELDS =\
|
||||
getattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS',
|
||||
('BooleanField',))
|
||||
except IndexError:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ def add_localized_fields(model):
|
|||
for field_name in translation_opts.fields:
|
||||
localized_fields[field_name] = list()
|
||||
for l in settings.LANGUAGES:
|
||||
# Create a dynamic translation field
|
||||
translation_field = create_translation_field(model=model,\
|
||||
field_name=field_name, lang=l[0])
|
||||
# Construct the name for the localized field
|
||||
localized_field_name = build_localized_fieldname(field_name, l[0])
|
||||
# Check if the model already has a field by that name
|
||||
|
|
@ -63,9 +66,6 @@ def add_localized_fields(model):
|
|||
"already contains a field named '%s'." %\
|
||||
(instance.__class__.__name__,
|
||||
localized_field_name))
|
||||
# Create a dynamic translation field
|
||||
translation_field = create_translation_field(model=model,\
|
||||
field_name=field_name, lang=l[0])
|
||||
# This approach implements the translation fields as full valid
|
||||
# django model fields and therefore adds them via add_to_class
|
||||
localized_field = model.add_to_class(localized_field_name,
|
||||
|
|
|
|||
Loading…
Reference in a new issue