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)
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)
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