예제 #1
0
    def __new__(cls, name, bases, attrs):
        ### START - Build translation model
        # At first we build translation model so we can add it to attrs
        # Purpose is to not call 'add_to_class' after model is registered

        # We have to copy attributes because they change during creation of a model
        trans_attrs = attrs.copy()

        # Make a copy of Meta, so changes in it when creating a translation model does not affect
        # creation of multilingual model
        if attrs.has_key('Meta'):
            trans_attrs['Meta'] = classobj.__new__(classobj, 'Meta', (attrs['Meta'],), attrs['Meta'].__dict__.copy())

        translation_name = name + "Translation"
        trans_attrs['multilingual_model_name'] = name
        c_trans_model = TranslationModelBase(translation_name, (TranslationModel, ), trans_attrs)
        ### END - Build translation model

        ### And some changes before we build multilingual model
        meta = attrs.get('Meta', None)
        abstract = getattr(meta, 'abstract', False)

        # Add translation model to attrs
        attrs['translation_model'] = c_trans_model

        if not abstract:
            # Add translation relations
            for language_code in [None] + get_all():
                field = TranslationRelation(c_trans_model, base_name=TRANSLATION_FIELD_NAME,
                                            language_code=language_code)
                attrs[field.name] = field

            # Add proxies for translated fields into attrs
            for field in (c_trans_model._meta.fields + c_trans_model._meta.many_to_many):
                if field.name in ('id', 'language_code', 'master'):
                    continue
                for language_code in get_all():
                    proxy = TranslationProxyField(field.name, language_code)
                    attrs[proxy.name] = proxy
                proxy = TranslationProxyField(field.name, None)
                attrs[proxy.name] = proxy
                proxy = TranslationProxyField(field.name, None, fallback=True)
                attrs[proxy.name] = proxy

        # Handle manager
        if not 'objects' in attrs:
            # If there is no manager, set MultilingualManager as manager
            attrs['objects'] = MultilingualManager()
        elif not isinstance(attrs['objects'], MultilingualManager):
            # Make sure that if the class specifies objects then it is a subclass of our Manager.

            # Don't check other managers since someone might want to have a non-multilingual manager, but assigning
            # a non-multilingual manager to objects would be a common mistake.
            raise ValueError("Model %s specifies translations, so its 'objects' manager must be a subclass of "\
                             "multilingual.Manager." % name)

        # And now just create multilingual model
        return super(MultilingualModelBase, cls).__new__(cls, name, bases, attrs)
	def __new__(cls, name, bases, attrs):
		# This only happens for base multilingual models
		if not attrs.has_key('Translation'):
			#TODO: CHECK attrs here
			super_new = super(TranslationModelBase, cls).__new__
			return super_new(cls, name, bases, attrs)

		# multilingual meta
		attr_meta = attrs.pop('Meta', None)

		# Prepare attributes for translation model
		trans_attrs = attrs['Translation'].__dict__.copy()
		trans_attrs.pop('__doc__')
		# original Meta of Translation Model
		trans_meta = trans_attrs.pop('Meta', None)

		### START - Create Meta for TranslationModel
		meta_attrs = getattr(trans_meta, '__dict__', {})
		for key in META_INHERITES:
			if hasattr(attr_meta, key):
				meta_attrs[key] = getattr(attr_meta, key)

		# Append suffix to db_table of multilingual class
		if not meta_attrs.has_key('db_table') and hasattr(attr_meta, 'db_table'):
			meta_attrs['db_table'] = attr_meta.db_table + 'translation'

		# Handle unique constraints
		meta_attrs['unique_together'] = list(meta_attrs.get('unique_together', []))
		meta_attrs['unique_together'] = [
		tuple(list(item) + ['language_code'])
		for item in meta_attrs['unique_together']
		]
		# append all unique fields to unique_together with 'language_code' field
		# and remove their uniqueness
		for item_name, item in trans_attrs.items():
			if isinstance(item, models.Field) and item.unique and not item.primary_key:
				meta_attrs['unique_together'].append((item_name, 'language_code'))
				trans_attrs[item_name]._unique = False
			# TODO: use TranslationModel.Meta instead of hardcoding
		# Appending necessary unique together
		meta_attrs['unique_together'].append(('language_code', 'master'))

		# TODO: enable related_name in Options
		related_name = meta_attrs.pop('related_name', 'translations')

		# TODO: use something already existing instead of BaseTranslationMeta
		trans_attrs['Meta'] = classobj.__new__(classobj, 'Meta', (BaseTranslationMeta,), meta_attrs)
		### END - Create Meta for TranslationModel

		# Add 'master' field
		trans_attrs['master'] = models.ForeignKey(
			attrs['multilingual_model_name'],
			related_name=related_name
		)

		return super(TranslationModelBase, cls).__new__(cls, name, bases, trans_attrs)
예제 #3
0
    def __new__(cls, name, bases, attrs):
        ### START - Build translation model
        # At first we build translation model so we can add it to attrs
        # Purpose is to not call 'add_to_class' after model is registered

        # We have to copy attributes because they change during creation of a model
        trans_attrs = attrs.copy()

        # Make a copy of Meta, so changes in it when creating a translation model does not affect
        # creation of multilingual model
        if attrs.has_key("Meta"):
            trans_attrs["Meta"] = classobj.__new__(classobj, "Meta", (attrs["Meta"],), attrs["Meta"].__dict__.copy())

        translation_name = name + "Translation"
        trans_attrs["multilingual_model_name"] = name
        c_trans_model = TranslationModelBase(translation_name, (TranslationModel,), trans_attrs)
        ### END - Build translation model

        ### And some changes before we build multilingual model
        # Add translation model to attrs
        attrs["translation_model"] = c_trans_model

        # Add proxies for translated fields into attrs
        for field in c_trans_model._meta.fields:
            if field.name in ("id", "language_code", "master"):
                continue
            for language_code in get_all():
                proxy = TranslationProxyField(field.name, language_code)
                attrs[proxy.name] = proxy
            proxy = TranslationProxyField(field.name, None)
            attrs[proxy.name] = proxy
            proxy = TranslationProxyField(field.name, None, fallback=True)
            attrs[proxy.name] = proxy

            # Handle manager
        if not "objects" in attrs:
            # If there is no manager, set MultilingualManager as manager
            attrs["objects"] = MultilingualManager()
        elif not isinstance(attrs["objects"], MultilingualManager):
            # Make sure that if the class specifies objects then it is a subclass of our Manager.

            # Don't check other managers since someone might want to have a non-multilingual manager, but assigning
            # a non-multilingual manager to objects would be a common mistake.
            raise ValueError(
                "Model %s specifies translations, so its 'objects' manager must be a subclass of "
                "multilingual.Manager." % name
            )

            # And now just create multilingual model
        return super(MultilingualModelBase, cls).__new__(cls, name, bases, attrs)