class ManyRelatedObjectsDescriptor(object): # This class provides the functionality that makes the related-object # managers available as attributes on a model class, for fields that have # multiple "remote" values and have a ManyToManyField pointed at them by # some other model (rather than having a ManyToManyField themselves). # In the example "publication.article_set", the article_set attribute is a # ManyRelatedObjectsDescriptor instance. def __init__(self, related): self.related = related # RelatedObject instance def __get__(self, instance, instance_type=None): if instance is None: raise AttributeError, "Manager must be accessed via instance" # Dynamically create a class that subclasses the related # model's default manager. rel_model = self.related.model superclass = rel_model._default_manager.__class__ RelatedManager = create_many_related_manager(superclass) qn = connection.ops.quote_name manager = RelatedManager( model=rel_model, core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()}, instance=instance, symmetrical=False, join_table=qn(self.related.field.m2m_db_table()), source_col_name=qn(self.related.field.m2m_reverse_name()), target_col_name=qn(self.related.field.m2m_column_name()), field_name=self.related.field.name ) return manager def __set__(self, instance, value): if instance is None: raise AttributeError, "Manager must be accessed via instance" manager = self.__get__(instance) manager.clear() manager.add(*value) class ReverseManyRelatedObjectsDescriptor(object): # This class provides the functionality that makes the related-object # managers available as attributes on a model class, for fields that have # multiple "remote" values and have a ManyToManyField defined in their # model (rather than having another model pointed *at* them). # In the example "article.publications", the publications attribute is a # ReverseManyRelatedObjectsDescriptor instance. def __init__(self, m2m_field): self.field = m2m_field def __get__(self, instance, instance_type=None): if instance is None: raise AttributeError, "Manager must be accessed via instance" # Dynamically create a class that subclasses the related # model's default manager. rel_model=self.field.rel.to superclass = rel_model._default_manager.__class__ RelatedManager = create_many_related_manager(superclass) qn = connection.ops.quote_name manager = RelatedManager( model=rel_model, core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()}, instance=instance, symmetrical=(self.field.rel.symmetrical and instance.__class__ == rel_model), join_table=qn(self.field.m2m_db_table()), source_col_name=qn(self.field.m2m_column_name()), target_col_name=qn(self.field.m2m_reverse_name()), field_name=self.field.name ) return manager def __set__(self, instance, value): if instance is None: raise AttributeError, "Manager must be accessed via instance" manager = self.__get__(instance) manager.clear() manager.add(*value)