def _patch_panel(model, panel): """ Generic panel patching function """ WagtailTranslator._current_model = model WagtailTranslator._translation_options = translator.get_options_for_model( model) if model not in WagtailTranslator._required_fields: WagtailTranslator._required_fields[model] = [] if panel.__class__.__name__ == 'FieldPanel': trpanels = WagtailTranslator._patch_fieldpanel(panel) elif panel.__class__.__name__ == 'ImageChooserPanel': trpanels = WagtailTranslator._patch_imagechooser(panel) elif panel.__class__.__name__ == 'MultiFieldPanel': trpanels = [WagtailTranslator._patch_multifieldpanel(panel)] elif panel.__class__.__name__ == 'InlinePanel': WagtailTranslator._patch_inlinepanel(model, panel) trpanels = [panel] elif panel.__class__.__name__ == 'StreamFieldPanel': trpanels = WagtailTranslator._patch_streamfieldpanel(panel) elif panel.__class__.__name__ == 'FieldRowPanel': trpanels = [WagtailTranslator._patch_fieldrowpanel(panel)] else: trpanels = [panel] return trpanels
def _patch_inlinepanel(cls, instance, panel): relation = getattr(instance.__class__, panel.relation_name) related_fieldname = 'related' try: inline_panels = getattr( getattr(relation, related_fieldname).model, 'panels', []) except AttributeError: related_fieldname = 'rel' inline_panels = getattr( getattr(relation, related_fieldname).model, 'panels', []) try: model = getattr(getattr(instance.__class__, panel.relation_name), related_fieldname).model inline_model_tr_fields = translator.get_options_for_model( model).fields except NotRegistered: return None translated_inline = [] for inlinepanel in inline_panels: for item in cls._patch_fieldpanel(inlinepanel, inline_model_tr_fields): translated_inline.append(item) model.panels = translated_inline
def _patch_panel(model, panel): """ Generic panel patching function """ WagtailTranslator._current_model = model WagtailTranslator._translation_options = translator.get_options_for_model(model) if model not in WagtailTranslator._required_fields: WagtailTranslator._required_fields[model] = [] if panel.__class__.__name__ == 'FieldPanel': trpanels = WagtailTranslator._patch_fieldpanel(panel) elif panel.__class__.__name__ == 'ImageChooserPanel': trpanels = WagtailTranslator._patch_imagechooser(panel) elif panel.__class__.__name__ == 'MultiFieldPanel': trpanels = [WagtailTranslator._patch_multifieldpanel(panel)] elif panel.__class__.__name__ == 'InlinePanel': WagtailTranslator._patch_inlinepanel(model, panel) trpanels = [panel] elif panel.__class__.__name__ == 'StreamFieldPanel': trpanels = WagtailTranslator._patch_streamfieldpanel(panel) elif panel.__class__.__name__ == 'FieldRowPanel': trpanels = [WagtailTranslator._patch_fieldrowpanel(panel)] else: trpanels = [panel] return trpanels
def _patch_inlinepanel(cls, model, panel): relation = getattr(model, panel.relation_name) related_fieldname = 'related' try: inline_panels = getattr( getattr(relation, related_fieldname).related_model, 'panels', []) except AttributeError: related_fieldname = 'rel' inline_panels = getattr( getattr(relation, related_fieldname).related_model, 'panels', []) try: related_model = getattr(getattr(model, panel.relation_name), related_fieldname).related_model WagtailTranslator._translation_options = translator.get_options_for_model( related_model) except NotRegistered: return None translated_inline = [] for inline_panel in inline_panels: for item in cls._patch_panel(related_model, inline_panel): translated_inline.append(item) related_model.panels = translated_inline
def handle_noargs(self, **options): verbosity = int(options['verbosity']) if verbosity > 0: self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE) models = translator.get_registered_models(abstract=False) for model in models: if verbosity > 0: self.stdout.write("Updating data of model '%s'\n" % model) opts = translator.get_options_for_model(model) for field_name in opts.fields.keys(): def_lang_fieldname = build_localized_fieldname( field_name, DEFAULT_LANGUAGE) # We'll only update fields which do not have an existing value q = Q(**{def_lang_fieldname: None}) field = model._meta.get_field(field_name) if field.empty_strings_allowed: q |= Q(**{def_lang_fieldname: ''}) if issubclass(model, Page): for obj in model._default_manager.filter(q): # Get table description in order to know if field is # in child or parent table # TODO: Tested only on PostgreSQL engine db_table = model._meta.db_table db_table_desc = connection.introspection.\ get_table_description( connection.cursor(), db_table) # original field in child class if field_name in [x.name for x in db_table_desc]: raw = model._default_manager.raw( 'SELECT *, %s AS original_field FROM %s \ WHERE page_ptr_id=%d LIMIT 1' % (field_name, db_table, obj.page_ptr_id))[0] setattr(obj, def_lang_fieldname, raw.original_field) # field is a foreign key elif (field_name + '_id') in\ [x.name for x in db_table_desc]: raw = model._default_manager.raw( 'SELECT *, %s AS original_field FROM %s \ WHERE page_ptr_id=%d LIMIT 1' % (field_name + '_id', db_table, obj.page_ptr_id))[0] setattr(obj, def_lang_fieldname + '_id', raw.original_field) # original field parent class else: raw = Page._default_manager.raw( 'SELECT *, %s AS original_field FROM \ wagtailcore_page WHERE id=%d LIMIT 1' % (field_name, obj.page_ptr_id))[0] setattr(obj, def_lang_fieldname, raw.original_field) obj.save(update_fields=[def_lang_fieldname]) else: model._default_manager.filter(q).rewrite(False).update( **{def_lang_fieldname: F(field_name)})
def append_translated(model, fields): "If translated field is encountered, add also all its translation fields." fields = set(fields) from wagtail_modeltranslation.translator import translator opts = translator.get_options_for_model(model) for key, translated in opts.fields.items(): if key in fields: fields = fields.union(f.name for f in translated) return fields
def handle_noargs(self, **options): verbosity = int(options['verbosity']) if verbosity > 0: self.stdout.write( "Using default language: %s\n" % DEFAULT_LANGUAGE) models = translator.get_registered_models(abstract=False) for model in models: if verbosity > 0: self.stdout.write("Updating data of model '%s'\n" % model) opts = translator.get_options_for_model(model) for field_name in opts.fields.keys(): def_lang_fieldname = build_localized_fieldname( field_name, DEFAULT_LANGUAGE) # We'll only update fields which do not have an existing value q = Q(**{def_lang_fieldname: None}) field = model._meta.get_field(field_name) if field.empty_strings_allowed: q |= Q(**{def_lang_fieldname: ''}) if issubclass(model, Page): for obj in model._default_manager.filter(q): # Get table description in order to know if field is # in child or parent table # TODO: Tested only on PostgreSQL engine db_table = model._meta.db_table db_table_desc = connection.introspection.\ get_table_description( connection.cursor(), db_table) # original field in child class if field_name in [x.name for x in db_table_desc]: raw = model._default_manager.raw( 'SELECT *, %s AS original_field FROM %s \ WHERE page_ptr_id=%d LIMIT 1' % ( field_name, db_table, obj.page_ptr_id))[0] setattr( obj, def_lang_fieldname, raw.original_field) # original field parent class else: raw = Page._default_manager.raw( 'SELECT *, %s AS original_field FROM \ wagtailcore_page WHERE id=%d LIMIT 1' % ( field_name, obj.page_ptr_id))[0] setattr( obj, def_lang_fieldname, raw.original_field) obj.save(update_fields=[def_lang_fieldname]) else: model._default_manager.filter(q).rewrite(False).update( **{def_lang_fieldname: F(field_name)})
def _patch_inlinepanel(cls, instance, panel): relation = getattr(instance.__class__, panel.relation_name) inline_panels = getattr(relation.related.model, 'panels', []) try: inline_model_tr_fields = translator.get_options_for_model( getattr( instance.__class__, panel.relation_name).related.model).fields except NotRegistered: return None translated_inline = [] for inlinepanel in inline_panels: for item in cls._patch_fieldpanel(inlinepanel, inline_model_tr_fields): translated_inline.append(item) getattr(instance.__class__, panel.relation_name).related.model.panels = translated_inline
def append_fallback(model, fields): """ If translated field is encountered, add also all its fallback fields. Returns tuple: (set_of_new_fields_to_use, set_of_translated_field_names) """ fields = set(fields) trans = set() from wagtail_modeltranslation.translator import translator opts = translator.get_options_for_model(model) for key, _ in opts.fields.items(): if key in fields: langs = resolution_order(get_language(), getattr(model, key).fallback_languages) fields = fields.union(build_localized_fieldname(key, lang) for lang in langs) fields.remove(key) trans.add(key) return fields, trans
def handle_noargs(self, **options): """ Command execution. """ self.cursor = connection.cursor() self.introspection = connection.introspection self.interactive = options['interactive'] found_missing_fields = False models = translator.get_registered_models(abstract=False) for model in models: db_table = model._meta.db_table if django.VERSION < (1, 8): model_name = model._meta.module_name else: model_name = model._meta.model_name model_full_name = '%s.%s' % (model._meta.app_label, model_name) opts = translator.get_options_for_model(model) for field_name, fields in opts.local_fields.items(): # Take `db_column` attribute into account field = list(fields)[0] column_name = field.db_column if field.db_column else field_name missing_langs = list( self.get_missing_languages(column_name, db_table)) if missing_langs: found_missing_fields = True print_missing_langs(missing_langs, field_name, model_full_name) sql_sentences = self.get_sync_sql(field_name, missing_langs, model) execute_sql = ask_for_confirmation(sql_sentences, model_full_name, self.interactive) if execute_sql: print('Executing SQL...') for sentence in sql_sentences: self.cursor.execute(sentence) print('Done') else: print('SQL not executed') if django.VERSION < (1, 6): transaction.commit_unless_managed() if not found_missing_fields: print('No new translatable fields detected')
def _patch_inlinepanel(cls, instance, panel): relation = getattr(instance.__class__, panel.relation_name) inline_panels = getattr(relation.related.model, 'panels', []) try: inline_model_tr_fields = translator.get_options_for_model( getattr(instance.__class__, panel.relation_name).related.model).fields except NotRegistered: return None translated_inline = [] for inlinepanel in inline_panels: for item in cls._patch_fieldpanel(inlinepanel, inline_model_tr_fields): translated_inline.append(item) getattr(instance.__class__, panel.relation_name).related.model.panels =\ translated_inline
def handle_noargs(self, **options): """ Command execution. """ self.cursor = connection.cursor() self.introspection = connection.introspection self.interactive = options['interactive'] found_missing_fields = False models = translator.get_registered_models(abstract=False) for model in models: db_table = model._meta.db_table if django.VERSION < (1, 8): model_name = model._meta.module_name else: model_name = model._meta.model_name model_full_name = '%s.%s' % (model._meta.app_label, model_name) opts = translator.get_options_for_model(model) for field_name, fields in opts.local_fields.items(): # Take `db_column` attribute into account field = list(fields)[0] column_name = field.db_column if field.db_column else field_name missing_langs = list(self.get_missing_languages(column_name, db_table)) if missing_langs: found_missing_fields = True print_missing_langs(missing_langs, field_name, model_full_name) sql_sentences = self.get_sync_sql(field_name, missing_langs, model) execute_sql = ask_for_confirmation( sql_sentences, model_full_name, self.interactive) if execute_sql: print('Executing SQL...') for sentence in sql_sentences: self.cursor.execute(sentence) print('Done') else: print('SQL not executed') if django.VERSION < (1, 6): transaction.commit_unless_managed() if not found_missing_fields: print('No new translatable fields detected')
def handle_noargs(self, **options): verbosity = int(options['verbosity']) if verbosity > 0: self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE) models = translator.get_registered_models(abstract=False) for model in models: if verbosity > 0: self.stdout.write("Updating data of model '%s'\n" % model) opts = translator.get_options_for_model(model) for field_name in opts.fields.keys(): def_lang_fieldname = build_localized_fieldname(field_name, DEFAULT_LANGUAGE) # We'll only update fields which do not have an existing value q = Q(**{def_lang_fieldname: None}) field = model._meta.get_field(field_name) if field.empty_strings_allowed: q |= Q(**{def_lang_fieldname: ""}) model._default_manager.filter(q).rewrite(False).update( **{def_lang_fieldname: F(field_name)})
def _patch_inlinepanel(cls, model, panel): relation = getattr(model, panel.relation_name) related_fieldname = 'related' try: inline_panels = getattr(getattr(relation, related_fieldname).related_model, 'panels', []) except AttributeError: related_fieldname = 'rel' inline_panels = getattr(getattr(relation, related_fieldname).related_model, 'panels', []) try: related_model = getattr(getattr(model, panel.relation_name), related_fieldname).related_model WagtailTranslator._translation_options = translator.get_options_for_model(related_model) except NotRegistered: return None translated_inline = [] for inline_panel in inline_panels: for item in cls._patch_panel(related_model, inline_panel): translated_inline.append(item) related_model.panels = translated_inline
def handle_noargs(self, **options): verbosity = int(options['verbosity']) if verbosity > 0: self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE) models = translator.get_registered_models(abstract=False) for model in models: if verbosity > 0: self.stdout.write("Updating data of model '%s'\n" % model) opts = translator.get_options_for_model(model) for field_name in opts.fields.keys(): def_lang_fieldname = build_localized_fieldname( field_name, DEFAULT_LANGUAGE) # We'll only update fields which do not have an existing value q = Q(**{def_lang_fieldname: None}) field = model._meta.get_field(field_name) if field.empty_strings_allowed: q |= Q(**{def_lang_fieldname: ""}) model._default_manager.filter(q).rewrite(False).update( **{def_lang_fieldname: F(field_name)})
def __init__(self, translated_field, language, empty_value, *args, **kwargs): from wagtail_modeltranslation.translator import translator # Update the dict of this field with the content of the original one # This might be a bit radical?! Seems to work though... self.__dict__.update(translated_field.__dict__) # Store the originally wrapped field for later self.translated_field = translated_field self.language = language self.empty_value = empty_value if empty_value is NONE: self.empty_value = None if translated_field.null else '' # Default behaviour is that all translations are optional if not isinstance(self, fields.BooleanField): # TODO: Do we really want to enforce null *at all*? Shouldn't this # better honour the null setting of the translated field? self.null = True self.blank = True # Take required_languages translation option into account trans_opts = translator.get_options_for_model(self.model) if trans_opts.required_languages: required_languages = trans_opts.required_languages if isinstance(trans_opts.required_languages, (tuple, list)): # All fields if self.language in required_languages: # self.null = False self.blank = False else: # Certain fields only # Try current language - if not present, try 'default' key try: req_fields = required_languages[self.language] except KeyError: req_fields = required_languages.get('default', ()) if self.name in req_fields: # TODO: We might have to handle the whole thing through the # FieldsAggregationMetaClass, as fields can be inherited. # self.null = False self.blank = False # Adjust the name of this field to reflect the language self.attname = build_localized_fieldname(self.translated_field.name, language) self.name = self.attname if self.translated_field.db_column: self.db_column = build_localized_fieldname(self.translated_field.db_column, language) self.column = self.db_column # Copy the verbose name and append a language suffix # (will show up e.g. in the admin). self.verbose_name = build_localized_verbose_name(translated_field.verbose_name, language) # ForeignKey support - rewrite related_name 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. # self.related doesn't need to be copied, as it will be recreated in # ``RelatedField.do_related_class`` if self.rel.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.rel.related_name = build_localized_fieldname(current, self.language) 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
def get_translatable_fields_for_model(model): from wagtail_modeltranslation.translator import NotRegistered, translator try: return translator.get_options_for_model(model).get_field_names() except NotRegistered: return None
def __init__(self, translated_field, language, empty_value, *args, **kwargs): from wagtail_modeltranslation.translator import translator # Update the dict of this field with the content of the original one # This might be a bit radical?! Seems to work though... self.__dict__.update(translated_field.__dict__) # Store the originally wrapped field for later self.translated_field = translated_field self.language = language self.empty_value = empty_value if empty_value is NONE: self.empty_value = None if translated_field.null else '' # Default behaviour is that all translations are optional if not isinstance(self, fields.BooleanField): # TODO: Do we really want to enforce null *at all*? Shouldn't this # better honour the null setting of the translated field? self.null = True self.blank = True # Take required_languages translation option into account trans_opts = translator.get_options_for_model(self.model) if trans_opts.required_languages: required_languages = trans_opts.required_languages if isinstance(trans_opts.required_languages, (tuple, list)): # All fields if self.language in required_languages: # self.null = False self.blank = False else: # Certain fields only # Try current language - if not present, try 'default' key try: req_fields = required_languages[self.language] except KeyError: req_fields = required_languages.get('default', ()) if self.name in req_fields: # TODO: We might have to handle the whole thing through the # FieldsAggregationMetaClass, as fields can be inherited. # self.null = False self.blank = False # Adjust the name of this field to reflect the language self.attname = build_localized_fieldname(self.translated_field.name, language) self.name = self.attname if self.translated_field.db_column: self.db_column = build_localized_fieldname( self.translated_field.db_column, language) self.column = self.db_column # Copy the verbose name and append a language suffix # (will show up e.g. in the admin). self.verbose_name = build_localized_verbose_name( translated_field.verbose_name, language) # ForeignKey support - rewrite related_name 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. # self.related doesn't need to be copied, as it will be recreated in # ``RelatedField.do_related_class`` if self.rel.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.rel.related_name = build_localized_fieldname( current, self.language) 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