예제 #1
0
def prepare_translatable_model(sender, **kwargs):
    model = sender
    if not issubclass(model, TranslatableModel) or model._meta.abstract:
        return

    if model._meta.proxy:
        model._meta.translations_accessor = model._meta.concrete_model._meta.translations_accessor
        model._meta.translations_model = model._meta.concrete_model._meta.translations_model
        model._meta.translations_cache = model._meta.concrete_model._meta.translations_cache

    if not hasattr(model._meta, 'translations_model'):
        raise ImproperlyConfigured(
            "No TranslatedFields found on %r, subclasses of "
            "TranslatableModel must define TranslatedFields." % model)

    #### Now we have to work ####

    # Ensure _base_manager cannot be TranslationManager despite use_for_related_fields
    # 1- it is useless unless default_class is overriden
    # 2- in that case, _base_manager is used for saving objects and must not be
    #    translation aware.
    base_mgr = getattr(model, '_base_manager', None)
    if base_mgr is None or isinstance(base_mgr, TranslationManager):
        assert django.VERSION < (1, 10)
        model.add_to_class('_base_manager', Manager())

    # Replace get_field_by_name with one that warns for common mistakes
    if django.VERSION < (1, 9) and not isinstance(
            model._meta.get_field_by_name, SmartGetFieldByName):
        model._meta.get_field_by_name = MethodType(
            SmartGetFieldByName(model._meta.get_field_by_name), model._meta)
    if not isinstance(model._meta.get_field, SmartGetField):
        model._meta.get_field = MethodType(
            SmartGetField(model._meta.get_field), model._meta)
예제 #2
0
def prepare_translatable_model(sender, **kwargs):
    model = sender
    if not issubclass(model, TranslatableModel) or model._meta.abstract:
        return
    if not isinstance(model._default_manager, TranslationManager):
        raise ImproperlyConfigured(
            "The default manager on a TranslatableModel must be a "
            "TranslationManager instance or an instance of a subclass of "
            "TranslationManager, the default manager of %r is not." % model)

    # If this is a proxy model, get the concrete one
    concrete_model = model._meta.concrete_model if model._meta.proxy else model

    # Find the instance of TranslatedFields in the concrete model's dict
    found = None
    for relation in list(concrete_model.__dict__.keys()):
        try:
            obj = getattr(model, relation)
            shared_model = obj.related.model._meta.shared_model
        except AttributeError:
            continue
        if shared_model is concrete_model:
            if found:
                raise ImproperlyConfigured(
                    "A TranslatableModel can only define one set of "
                    "TranslatedFields, %r defines more than one: %r to %r "
                    "and %r to %r and possibly more" % (model, obj,
                    obj.related.model, found, found.related.model))
            # Mark as found but keep looking so we catch duplicates and raise
            found = obj

    if not found:
        raise ImproperlyConfigured(
            "No TranslatedFields found on %r, subclasses of "
            "TranslatableModel must define TranslatedFields." % model
        )

    #### Now we have to work ####

    contribute_translations(model, found.related)

    # Ensure _base_manager cannot be TranslationManager despite use_for_related_fields
    # 1- it is useless unless default_class is overriden
    # 2- in that case, _base_manager is used for saving objects and must not be
    #    translation aware.
    base_mgr = getattr(model, '_base_manager', None)
    if base_mgr is None or isinstance(base_mgr, TranslationManager):
        model.add_to_class('_base_manager', Manager())

    # Replace get_field_by_name with one that warns for common mistakes
    if not isinstance(model._meta.get_field_by_name, SmartGetFieldByName):
        smart_get_field_by_name = SmartGetFieldByName(model._meta.get_field_by_name)
        model._meta.get_field_by_name = MethodType(smart_get_field_by_name , model._meta)

    # Attach save_translations
    post_save.connect(model.save_translations, sender=model, weak=False)
예제 #3
0
    def __new__(cls, name, bases, attrs):
        super_new = super(TranslatableModelBase, cls).__new__
        parents = [b for b in bases if isinstance(b, TranslatableModelBase)]
        if not parents:
            # If this isn't a subclass of TranslatableModel, don't do anything special.
            return super_new(cls, name, bases, attrs)
        new_model = super_new(cls, name, bases, attrs)
        if not isinstance(new_model.objects, TranslationManager):
            raise ImproperlyConfigured(
                "The default manager on a TranslatableModel must be a "
                "TranslationManager instance or an instance of a subclass of "
                "TranslationManager, the default manager of %r is not." %
                new_model)
        
        opts = new_model._meta
        if opts.abstract:
            return new_model
        
        found = False
        for relation in new_model.__dict__.keys():
            try:
                obj = getattr(new_model, relation)
            except AttributeError:
                continue
            if not hasattr(obj, 'related'):
                continue
            if not hasattr(obj.related, 'model'):
                continue
            if getattr(obj.related.model._meta, 'shared_model', None) is new_model:
                if found:
                    raise ImproperlyConfigured(
                        "A TranslatableModel can only define one set of "
                        "TranslatedFields, %r defines more than one: %r to %r "
                        "and %r to %r and possibly more" % (new_model, obj,
                        obj.related.model, found, found.related.model))
                else:
                    new_model.contribute_translations(obj.related)
                    found = obj

        if not found:
            raise ImproperlyConfigured(
                "No TranslatedFields found on %r, subclasses of "
                "TranslatableModel must define TranslatedFields." % new_model
            )
        
        post_save.connect(new_model.save_translations, sender=new_model, weak=False)
        
        if not isinstance(opts.get_field_by_name, SmartGetFieldByName):
            smart_get_field_by_name = SmartGetFieldByName(opts.get_field_by_name)
            opts.get_field_by_name = MethodType(smart_get_field_by_name , opts,
                                                opts.__class__)
        
        return new_model