Exemple #1
0
    def _register_single_model(self, model, opts):
        # Now, when all fields are initialized and inherited, validate configuration.
        opts.validate()

        # Mark the object explicitly as registered -- registry caches
        # options of all models, registered or not.
        opts.registered = True

        # Add translation fields to the model.
        if model._meta.proxy:
            delete_cache_fields(model)
        else:
            add_translation_fields(model, opts)

        # Delete all fields cache for related model (parent and children)
        related = ((
            f for f in model._meta.get_fields()
            if (f.one_to_many or f.one_to_one) and
            f.auto_created
        ) if NEW_RELATED_API else model._meta.get_all_related_objects())

        for related_obj in related:
            delete_cache_fields(related_obj.model)

        # Set MultilingualManager
        add_manager(model)

        # Patch __init__ to rewrite fields
        patch_constructor(model)

        # Connect signal for model
        if NEW_DEFERRED_API:
            post_init.connect(delete_mt_init, sender=model)
        else:
            # deferred models have their own classes and the `sender` does not match.
            # Connect signal for all models.
            post_init.connect(delete_mt_init, dispatch_uid="modeltranslation")

        # Patch clean_fields to verify form field clearing
        patch_clean_fields(model)

        # Patch __metaclass__ and other methods to allow deferring to work
        if not NEW_DEFERRED_API:
            patch_metaclass(model)
        patch_get_deferred_fields(model)
        patch_refresh_from_db(model)

        # Substitute original field with descriptor
        model_fallback_languages = getattr(opts, 'fallback_languages', None)
        model_fallback_values = getattr(opts, 'fallback_values', NONE)
        model_fallback_undefined = getattr(opts, 'fallback_undefined', NONE)
        for field_name in opts.local_fields.keys():
            field = model._meta.get_field(field_name)
            field_fallback_value = parse_field(model_fallback_values, field_name, NONE)
            field_fallback_undefined = parse_field(model_fallback_undefined, field_name, NONE)
            descriptor = TranslationFieldDescriptor(
                field,
                fallback_languages=model_fallback_languages,
                fallback_value=field_fallback_value,
                fallback_undefined=field_fallback_undefined)
            setattr(model, field_name, descriptor)
            if isinstance(field, ForeignKey):
                # We need to use a special descriptor so that
                # _id fields on translated ForeignKeys work
                # as expected.
                desc = TranslatedRelationIdDescriptor(field_name, model_fallback_languages)
                setattr(model, field.get_attname(), desc)

                # Set related field names on other model
                if NEW_RELATED_API and not field.remote_field.is_hidden():
                    other_opts = self._get_options_for_model(field.remote_field.to)
                    other_opts.related = True
                    other_opts.related_fields.append(field.related_query_name())
                    # Add manager in case of non-registered model
                    add_manager(field.remote_field.to)
                elif not NEW_RELATED_API and not field.rel.is_hidden():
                    other_opts = self._get_options_for_model(field.rel.to)
                    other_opts.related = True
                    other_opts.related_fields.append(field.related_query_name())
                    add_manager(field.rel.to)  # Add manager in case of non-registered model

            if isinstance(field, OneToOneField):
                # Fix translated_field caching for SingleRelatedObjectDescriptor
                sro_descriptor = (
                    getattr(field.remote_field.to, field.remote_field.get_accessor_name())
                    if NEW_RELATED_API
                    else getattr(field.rel.to, field.related.get_accessor_name()))
                patch_related_object_descriptor_caching(sro_descriptor)
    def register(self, model_or_iterable, opts_class=None, **options):
        """
        Registers the given model(s) with the given translation options.

        The model(s) should be Model classes, not instances.

        Fields declared for translation on a base class are inherited by
        subclasses. If the model or one of its subclasses is already
        registered for translation, this will raise an exception.
        """
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]

        for model in model_or_iterable:
            # Ensure that a base is not registered after a subclass (_registry
            # is closed with respect to taking bases, so we can just check if
            # we've seen the model).
            if model in self._registry:
                if self._registry[model].registered:
                    raise AlreadyRegistered(
                        'Model "%s" is already registered for translation' %
                        model.__name__)
                else:
                    descendants = [
                        d.__name__ for d in self._registry.keys()
                        if issubclass(d, model) and d != model
                    ]
                    raise DescendantRegistered(
                        'Model "%s" cannot be registered after its subclass'
                        ' "%s"' % (model.__name__, descendants[0]))

            # Find inherited fields and create options instance for the model.
            opts = self._get_options_for_model(model, opts_class, **options)

            # Now, when all fields are initialized and inherited, validate configuration.
            opts.validate()

            # Mark the object explicitly as registered -- registry caches
            # options of all models, registered or not.
            opts.registered = True

            # Add translation fields to the model.
            if model._meta.proxy:
                delete_cache_fields(model)
            else:
                add_translation_fields(model, opts)

            # Delete all fields cache for related model (parent and children)
            for related_obj in model._meta.get_all_related_objects():
                delete_cache_fields(related_obj.model)

            # Set MultilingualManager
            add_manager(model)

            # Patch __init__ to rewrite fields
            patch_constructor(model)

            # Connect signal for model
            post_init.connect(delete_mt_init, sender=model)

            # Patch clean_fields to verify form field clearing
            patch_clean_fields(model)

            # Patch __metaclass__ and other methods to allow deferring to work
            patch_metaclass(model)
            patch_get_deferred_fields(model)

            # Substitute original field with descriptor
            model_fallback_languages = getattr(opts, 'fallback_languages',
                                               None)
            model_fallback_values = getattr(opts, 'fallback_values', NONE)
            model_fallback_undefined = getattr(opts, 'fallback_undefined',
                                               NONE)
            for field_name in opts.local_fields.keys():
                field = model._meta.get_field(field_name)
                field_fallback_value = parse_field(model_fallback_values,
                                                   field_name, NONE)
                field_fallback_undefined = parse_field(
                    model_fallback_undefined, field_name, NONE)
                descriptor = TranslationFieldDescriptor(
                    field,
                    fallback_languages=model_fallback_languages,
                    fallback_value=field_fallback_value,
                    fallback_undefined=field_fallback_undefined)
                setattr(model, field_name, descriptor)
                if isinstance(field, ForeignKey):
                    # We need to use a special descriptor so that
                    # _id fields on translated ForeignKeys work
                    # as expected.
                    desc = TranslatedRelationIdDescriptor(
                        field_name, model_fallback_languages)
                    setattr(model, field.get_attname(), desc)

                    # Set related field names on other model
                    if not field.rel.is_hidden():
                        other_opts = self._get_options_for_model(field.rel.to)
                        other_opts.related = True
                        other_opts.related_fields.append(
                            field.related_query_name())
                        add_manager(
                            field.rel.to
                        )  # Add manager in case of non-registered model

                if isinstance(field, OneToOneField):
                    # Fix translated_field caching for SingleRelatedObjectDescriptor
                    sro_descriptor = getattr(field.rel.to,
                                             field.related.get_accessor_name())
                    patch_related_object_descriptor_caching(sro_descriptor)
    def register(self, model_or_iterable, translation_opts, **options):
        """
        Registers the given model(s) with the given translation options.

        The model(s) should be Model classes, not instances.

        If a model is already registered for translation, this will raise
        AlreadyRegistered.
        """
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]

        for model in model_or_iterable:
            if model in self._registry:
                raise AlreadyRegistered('The model %s is already registered '
                                        'for translation' % model.__name__)

            # If we got **options then dynamically construct a subclass of
            # translation_opts with those **options.
            if options:
                # For reasons I don't quite understand, without a __module__
                # the created class appears to "live" in the wrong place,
                # which causes issues later on.
                options['__module__'] = __name__
                translation_opts = type(
                    "%sTranslationOptions" % model.__name__,
                    (translation_opts,), options)

            # Store the translation class associated to the model
            self._registry[model] = translation_opts

            # Add the localized fields to the model and store the names of
            # these fields in the model's translation options for faster lookup
            # later on.
            translation_opts.localized_fieldnames = add_localized_fields(model)

            # Create a reverse dict mapping the localized_fieldnames to the
            # original fieldname
            rev_dict = dict()
            for orig_name, loc_names in \
                    translation_opts.localized_fieldnames.items():
                for ln in loc_names:
                    rev_dict[ln] = orig_name
            translation_opts.localized_fieldnames_rev = rev_dict

            # Delete all fields cache for related model (parent and children)
            for related_obj in model._meta.get_all_related_objects():
                delete_cache_fields(related_obj.model)

            # Set MultilingualManager
            add_manager(model)

            # Patch __init__ to rewrite fields
            patch_constructor(model)

            # Substitute original field with descriptor
            model_fallback_values = getattr(
                translation_opts, 'fallback_values', None)
            model_fallback_languages = getattr(
                translation_opts, 'fallback_languages', None)
            for field_name in translation_opts.fields:
                if model_fallback_values is None:
                    field_fallback_value = None
                elif isinstance(model_fallback_values, dict):
                    field_fallback_value = model_fallback_values.get(
                        field_name, None)
                else:
                    field_fallback_value = model_fallback_values
                descriptor = TranslationFieldDescriptor(
                    model._meta.get_field(field_name),
                    fallback_value=field_fallback_value,
                    fallback_languages=model_fallback_languages)
                setattr(model, field_name, descriptor)
Exemple #4
0
    def register(self, model_or_iterable, translation_opts, **options):
        """
        Registers the given model(s) with the given translation options.

        The model(s) should be Model classes, not instances.

        If a model is already registered for translation, this will raise
        AlreadyRegistered.
        """
        # Don't import the humongous validation code unless required
        if translation_opts and settings.DEBUG:
            from django.contrib.admin.validation import validate
        else:
            validate = lambda model, adminclass: None

        #if not translation_opts:
            #translation_opts = TranslationOptions
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]

        for model in model_or_iterable:
            if model in self._registry:
                raise AlreadyRegistered('The model %s is already registered '
                                        'for translation' % model.__name__)

            # If we got **options then dynamically construct a subclass of
            # translation_opts with those **options.
            if options:
                # For reasons I don't quite understand, without a __module__
                # the created class appears to "live" in the wrong place,
                # which causes issues later on.
                options['__module__'] = __name__
                translation_opts = type("%sAdmin" % model.__name__,
                                        (translation_opts,), options)

            # Validate (which might be a no-op)
            #validate(translation_opts, model)

            # Store the translation class associated to the model
            self._registry[model] = translation_opts

            # Get the content type of the original model and store it on the
            # translation options for faster lookup later on.
            #translation_opts.model_ct = \
                #ContentType.objects.get_for_model(model)

            # Add the localized fields to the model and store the names of
            # these fields in the model's translation options for faster lookup
            # later on.
            translation_opts.localized_fieldnames = add_localized_fields(model)

            # Create a reverse dict mapping the localized_fieldnames to the
            # original fieldname
            rev_dict = dict()
            for orig_name, loc_names in\
                translation_opts.localized_fieldnames.items():
                for ln in loc_names:
                    rev_dict[ln] = orig_name
            translation_opts.localized_fieldnames_rev = rev_dict

        model_fallback_values = getattr(translation_opts, 'fallback_values',
                                        None)
        for field_name in translation_opts.fields:
            # TODO: Check if fallback_value is set to a type that the field
            #       expects and raise ImproperlyConfigured in case it doesn't.
            if model_fallback_values is None:
                field_fallback_value = None
            elif isinstance(model_fallback_values, dict):
                field_fallback_value = model_fallback_values.get(field_name,
                                                                 None)
            else:
                field_fallback_value = model_fallback_values

            field = model._meta.get_field(field_name)
            field_class_name = field.rel.__class__.__name__
            if field_class_name in ('ManyToOneRel', 'OneToOneRel'):
                descriptor = RelatedTranslationFieldDescriptor(field_name,
                             fallback_value=field_fallback_value)
            elif field_class_name == 'ManyToManyRel':
                descriptor = ManyToManyTranslationFieldDescriptor(field_name,
                             fallback_value=field_fallback_value)
            else:
                descriptor = TranslationFieldDescriptor(field_name,
                             fallback_value=field_fallback_value)
            setattr(model, field_name, descriptor)
Exemple #5
0
    def register(self, model_or_iterable, translation_opts, **options):
        """
        Registers the given model(s) with the given translation options.

        The model(s) should be Model classes, not instances.

        If a model is already registered for translation, this will raise
        AlreadyRegistered.
        """
        # Don't import the humongous validation code unless required
        if translation_opts and settings.DEBUG:
            from django.contrib.admin.validation import validate
        else:
            validate = lambda model, adminclass: None

        #if not translation_opts:
        #translation_opts = TranslationOptions
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]

        for model in model_or_iterable:
            if model in self._registry:
                raise AlreadyRegistered('The model %s is already registered '
                                        'for translation' % model.__name__)

            # If we got **options then dynamically construct a subclass of
            # translation_opts with those **options.
            if options:
                # For reasons I don't quite understand, without a __module__
                # the created class appears to "live" in the wrong place,
                # which causes issues later on.
                options['__module__'] = __name__
                translation_opts = type("%sAdmin" % model.__name__,
                                        (translation_opts, ), options)

            # Validate (which might be a no-op)
            #validate(translation_opts, model)

            # Store the translation class associated to the model
            self._registry[model] = translation_opts

            # Get the content type of the original model and store it on the
            # translation options for faster lookup later on.
            #translation_opts.model_ct = \
            #ContentType.objects.get_for_model(model)

            # Add the localized fields to the model and store the names of
            # these fields in the model's translation options for faster lookup
            # later on.
            translation_opts.localized_fieldnames = add_localized_fields(model)

            # Create a reverse dict mapping the localized_fieldnames to the
            # original fieldname
            rev_dict = dict()
            for orig_name, loc_names in\
                translation_opts.localized_fieldnames.items():
                for ln in loc_names:
                    rev_dict[ln] = orig_name
            translation_opts.localized_fieldnames_rev = rev_dict

            # Delete all fields cache for related model (parent and children)
            related_classes = tuple(model.__bases__) \
                + tuple(model.__subclasses__())
            for related_model in related_classes:
                if related_model != models.Model \
                    and issubclass(related_model, models.Model):
                    delete_cache_fields(related_model)

        model_fallback_values =\
        getattr(translation_opts, 'fallback_values', None)
        for field_name in translation_opts.fields:
            if model_fallback_values is None:
                field_fallback_value = None
            elif isinstance(model_fallback_values, dict):
                field_fallback_value =\
                model_fallback_values.get(field_name, None)
            else:
                field_fallback_value = model_fallback_values
            setattr(model, field_name, TranslationFieldDescriptor(field_name,\
                    fallback_value=field_fallback_value))