def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError, "register() expects a Django model class argument" if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) # For backwards compatibility with existing libraries, we copy the # _mptt_meta options into _meta. # This will be removed in 0.5. # All new code should use _mptt_meta rather than _meta for tree attributes. for attr in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr', 'parent_attr', 'tree_manager_attr', 'order_insertion_by'): setattr(cls._meta, attr, getattr(cls._mptt_meta, attr)) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases)-1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a custom tree manager if not abstract: manager = TreeManager(cls._mptt_meta) manager.contribute_to_class(cls, cls._mptt_meta.tree_manager_attr) setattr(cls, '_tree_manager', getattr(cls, cls._mptt_meta.tree_manager_attr)) return cls
class Category(MPTTModel, ModelWithMetadata, SeoModel): name = models.CharField(max_length=250) slug = models.SlugField(max_length=255, unique=True, allow_unicode=True) description = SanitizedJSONField(blank=True, default=dict, sanitizer=clean_editor_js) description_json = SanitizedJSONField(blank=True, default=dict, sanitizer=clean_editor_js) parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE) background_image = VersatileImageField(upload_to="category-backgrounds", blank=True, null=True) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() def __str__(self) -> str: return self.name
class MenuItem(MPTTModel, SortableModel): menu = models.ForeignKey( Menu, related_name='items', on_delete=models.CASCADE) name = models.CharField(max_length=128) parent = models.ForeignKey( 'self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) # not mandatory fields, usage depends on what type of link is stored url = models.URLField(max_length=256, blank=True, null=True) category = models.ForeignKey( Category, blank=True, null=True, on_delete=models.CASCADE) collection = models.ForeignKey( Collection, blank=True, null=True, on_delete=models.CASCADE) page = models.ForeignKey( Page, blank=True, null=True, on_delete=models.CASCADE) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() class Meta: ordering = ('sort_order',) app_label = 'menu' def __str__(self): return self.name def get_ordering_queryset(self): return ( self.menu.items.all() if not self.parent else self.parent.children.all()) @property def linked_object(self): return self.category or self.collection or self.page @property def destination_display(self): linked_object = self.linked_object if not linked_object: prefix = pgettext_lazy('Link object type description', 'URL: ') return prefix + self.url if isinstance(linked_object, Category): prefix = pgettext_lazy( 'Link object type description', 'Category: ') elif isinstance(linked_object, Collection): prefix = pgettext_lazy( 'Link object type description', 'Collection: ') else: prefix = pgettext_lazy( 'Link object type description', 'Page: ') return prefix + str(linked_object) def get_url(self): linked_object = self.linked_object return linked_object.get_absolute_url() if linked_object else self.url
class CustomerStoreType(MPTTModel, TimeStampMixin): id = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False) code = models.SlugField(max_length=256, null=False, blank=False) name = models.TextField(null=False, blank=False) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) objects = models.Manager() tree = TreeManager() class Meta: app_label = 'customer_store' db_table = 'customer_store_type' permissions = ( ('view_customerstoretype', pgettext_lazy('Permission description', 'Can view customer store types')), ) def __str__(self): return f"{self.code} - {self.name}" def to_dict(self): if self.parent is not None: return {"code": self.code, "name": self.name, "parent": self.parent.to_dict()} else: return {"code": self.code, "name": self.name, "parent": self.parent} def get_detail(self, parent=False): if not parent: return {"code": self.code, "name": self.name} else: return {"code": self.code, "name": self.name, "parent": self.parent.to_dict()}
class Category(MPTTModel, SeoModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=128) description = models.TextField(blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) background_image = VersatileImageField(upload_to='category-backgrounds', blank=True, null=True) objects = models.Manager() tree = TreeManager() def __str__(self): return self.name def get_absolute_url(self, ancestors=None): return reverse('product:category', kwargs={ 'path': self.get_full_path(ancestors), 'category_id': self.id }) def get_full_path(self, ancestors=None): if not self.parent_id: return self.slug if not ancestors: ancestors = self.get_ancestors() nodes = [node for node in ancestors] + [self] return '/'.join([node.slug for node in nodes])
class BaseCategory(MPTTModel): title = models.CharField(_('title'), max_length=255) slug = models.SlugField(_('slug'), unique=True, max_length=255, help_text=_("Used to build the category's URL.")) description = models.TextField(_('description'), blank=True) parent = TreeForeignKey('self', related_name='children', null=True, blank=True, verbose_name=_('parent category')) objects = TreeManager() published = EntryRelatedPublishedManager() class Meta: ordering = ('title', ) abstract = True class MPTTMeta: order_insertion_by = ('title', ) def __unicode__(self): return self.title
class Category(MPTTModel, ModelWithMetadata, SeoModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=128) description = models.TextField(blank=True) description_json = JSONField(blank=True, default=dict) parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE) background_image = VersatileImageField(upload_to="category-backgrounds", blank=True, null=True) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() def __str__(self): return self.name def get_absolute_url(self): return reverse("product:category", kwargs={ "slug": self.slug, "category_id": self.id })
class Page(MPTTModel): TEMPLATE_CHOICES = getattr(settings, 'PAGE_TEMPLATES', ( ('', 'Default'), )) url = models.CharField('URL', max_length=100, unique=True, help_text="Example: '/about/contact/'. Make sure to have leading and " "trailing slashes.", validators=[url_validator, slash_validator]) title = models.CharField(max_length=200) parent = TreeForeignKey('self', null=True, blank=True, related_name='children') show_in_navigation = models.BooleanField(default=True, db_index=True) content = models.TextField(blank=True) template_name = models.CharField(max_length=100, blank=True, choices=TEMPLATE_CHOICES) published = models.BooleanField(default=True, db_index=True) login_required = models.BooleanField(default=False, editable=getattr(settings, 'PAGE_SHOW_LOGIN', False), db_index=True) is_system = models.BooleanField(default=False, db_index=True) objects = TreeManager() def __str__(self): return '%s -- %s' % (self.url, self.title) def get_absolute_url(self): # Handle script prefix manually because we bypass reverse() return iri_to_uri(get_script_prefix().rstrip('/') + self.url)
class Category(MPTTModel): # eg 1. Industrial fuel, 2. Chemical Products name = models.CharField(_('Category field', 'name'), max_length=200) slug = models.SlugField(_('Category field', 'slug'), max_length=200) description = models.TextField(_('Category field', 'description'), blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', verbose_name=_('Category field', 'parent')) hidden = models.BooleanField(_('Category field', 'hidden'), default=False) objects = models.Manager() tree = TreeManager() class Meta: verbose_name = _('Category model', 'category') verbose_name_plural = _('Category model', 'categories') app_label = 'product' permissions = ('vew_category', _('Permission description', 'Can view categories'), ('edit_category', _('Permission description', 'Can edit categories'))) def __str__(self): return self.name
class BaseMpttModel(MPTTModel): """基础字段""" FIELDS = ('creator', 'create_at', 'updated_by', 'update_at', 'end_at') creator = models.CharField(u"创建人", max_length=LEN_NORMAL, null=True, blank=True, default='system') create_at = models.DateTimeField(u"创建时间", auto_now_add=True) update_at = models.DateTimeField(u"更新时间", auto_now=True) updated_by = models.CharField(u"修改人", max_length=LEN_NORMAL, null=True, blank=True, default='system') end_at = models.DateTimeField(u"结束时间", null=True, blank=True) is_deleted = models.BooleanField(u"是否软删除", default=False, db_index=True) _objects = TreeManager() objects = managers.BaseTreeManager() class Meta: app_label = 'miscollection' abstract = True def delete(self, using=None): self.is_deleted = True self.save() def hard_delete(self, using=None): super(BaseMpttModel, self).delete()
class Category(MPTTModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=50) description = models.TextField(blank=True) parent = models.ForeignKey( 'self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) objects = models.Manager() tree = TreeManager() class Meta: app_label = 'product' permissions = ( ('view_category', pgettext_lazy('Permission description', 'Can view categories')), ('edit_category', pgettext_lazy('Permission description', 'Can edit categories'))) def __str__(self): return self.name def get_absolute_url(self, ancestors=None): return reverse('product:category', kwargs={'path': self.get_full_path(ancestors), 'category_id': self.id}) def get_full_path(self, ancestors=None): if not self.parent_id: return self.slug if not ancestors: ancestors = self.get_ancestors() nodes = [node for node in ancestors] + [self] return '/'.join([node.slug for node in nodes])
class Category(MPTTModel): # mens/womens/kids/uni name = models.CharField(max_length=128, unique=True) slug = AutoSlugField(populate_from='name', blank=True) description = models.TextField(blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) background_image = VersatileImageField(upload_to='category-backgrounds', blank=True, null=True) objects = models.Manager() tree = TreeManager() class Meta: ordering = ('-pk', ) def __str__(self): return self.name def get_absolute_url(self): return reverse('product_category_detail', args=(self.slug, )) def get_update_url(self): return reverse('product_category_update', args=(self.slug, ))
class Category(MPTTModel, SeoModel): name = models.CharField(max_length=250) slug = models.SlugField(max_length=255, unique=True) description = JSONField(blank=True, default=dict) parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE) background_image = VersatileImageField( upload_to=UploadToPathAndRename(path="category-backgrounds", field="name"), blank=True, null=True, ) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() class Meta: permissions = ((CategoryPermissions.MANAGE_CATEGORIES.codename, "Manage categories"), ) def __str__(self): return self.name
class BaseTermManager(RebuildTreeMixin, TreeManager.from_queryset(BaseTermQuerySet)): """ ENG: Customized model manager for our Term model. RUS: Адаптированная модель менеджера для модели Терминов. """ '''
class Category(MPTTModel, SeoModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=128) description = models.TextField(blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) background_image = VersatileImageField(upload_to='category-backgrounds', blank=True, null=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() def __str__(self): return self.name def get_absolute_url(self): return reverse('product:category', kwargs={ 'slug': self.slug, 'category_id': self.id })
class ServiceNode(MPTTModel): id = models.IntegerField(primary_key=True) name = models.CharField(max_length=200, db_index=True) parent = TreeForeignKey('self', null=True, related_name='children', on_delete=models.CASCADE) keywords = models.ManyToManyField(Keyword) service_reference = models.TextField(null=True) related_services = models.ManyToManyField(Service) last_modified_time = models.DateTimeField(db_index=True, help_text='Time of last modification') objects = CustomTreeManager() tree_objects = TreeManager() def __str__(self): return "%s (%s)" % (get_translated(self, 'name'), self.id) def get_unit_count(self): srv_list = set(ServiceNode.objects.all().by_ancestor(self).values_list('id', flat=True)) srv_list.add(self.id) count = Unit.objects.filter(public=True, service_nodes__in=list(srv_list)).distinct().count() return count def period_enabled(self): """Iterates through related services to find out if the tree node has periods enabled via services""" return next(( o.period_enabled for o in self.related_services.all() if o.period_enabled), False) class Meta: ordering = ['-pk']
class Page(MPTTModel): url = models.CharField( 'URL', max_length=100, unique=True, help_text= "Example: '/about/contact/'. Make sure to have leading and trailing slashes.", validators=[url_validator, slash_validator]) title = models.CharField(max_length=200) parent = TreeForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) show_in_navigation = models.BooleanField(default=True, db_index=True) hero_image = AssetForeignKey('assets.Image', blank=True, null=True, on_delete=models.SET_NULL) content = models.TextField(blank=True) template_name = models.CharField(max_length=100, blank=True) published = models.BooleanField(default=True, db_index=True) login_required = models.BooleanField(default=False, db_index=True) objects = TreeManager() def __str__(self): return '%s -- %s' % (self.url, self.title) def get_absolute_url(self): # Handle script prefix manually because we bypass reverse() return iri_to_uri(get_script_prefix().rstrip('/') + self.url)
class Category(ModelWithMetadata, MPTTModel, SeoModel): name = models.CharField(max_length=250) slug = models.SlugField(max_length=255, unique=True, allow_unicode=True) description = SanitizedJSONField(blank=True, null=True, sanitizer=clean_editor_js) description_plaintext = TextField(blank=True) parent = models.ForeignKey( "self", null=True, blank=True, related_name="children", on_delete=models.CASCADE ) background_image = VersatileImageField( upload_to="category-backgrounds", blank=True, null=True ) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() class Meta: indexes = [ *ModelWithMetadata.Meta.indexes, GinIndex( name="category_search_name_slug_gin", # `opclasses` and `fields` should be the same length fields=["name", "slug", "description_plaintext"], opclasses=["gin_trgm_ops"] * 3, ), ] def __str__(self) -> str: return self.name
class SectorsCategory(TimeStampedModel, MPTTModel): parent = TreeForeignKey( 'self', verbose_name=_('parent'), blank=True, null=True, related_name='children', db_index=True, on_delete=models.SET_NULL, ) title = models.CharField( verbose_name=_('title'), max_length=128, ) class MPTTMeta: order_insertion_by = ['created'] class Meta: verbose_name = _('카테고리 업종') verbose_name_plural = _('카테고리 업종') objects = TreeManager() def __str__(self): return self.title
class Category(MPTTModel, ModelWithMetadata, SeoModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=128) description = models.TextField(blank=True) description_json = JSONField(blank=True, default=dict) parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE) background_image = VersatileImageField(upload_to="category-backgrounds", blank=True, null=True) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() def __str__(self) -> str: return self.name # Deprecated. To remove in #5022 @staticmethod def get_absolute_url() -> str: return ""
class Category(MPTTModel): name = models.CharField( pgettext_lazy('Category field', 'name'), max_length=128) slug = models.SlugField( pgettext_lazy('Category field', 'slug'), max_length=50) description = models.TextField( pgettext_lazy('Category field', 'description'), blank=True) parent = models.ForeignKey( 'self', null=True, blank=True, related_name='children', verbose_name=pgettext_lazy('Category field', 'parent')) hidden = models.BooleanField( pgettext_lazy('Category field', 'hidden'), default=False) objects = Manager() tree = TreeManager() def __str__(self): return self.name def get_absolute_url(self): return reverse('product:category', kwargs={'path': self.get_full_path(), 'category_id': self.id}) def get_full_path(self): if not self.parent_id: return self.slug return '/'.join( [node.slug for node in self.get_ancestors(include_self=True)]) class Meta: verbose_name_plural = 'categories' app_label = 'product' def set_hidden_descendants(self, hidden): self.get_descendants().update(hidden=hidden)
class Page(MPTTModel, TranslatableModel): available_from = models.DateTimeField(null=True, blank=True, verbose_name=_('available from')) available_to = models.DateTimeField(null=True, blank=True, verbose_name=_('available to')) created_by = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name="+", on_delete=models.SET_NULL, verbose_name=_('created by') ) modified_by = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name="+", on_delete=models.SET_NULL, verbose_name=_('modified by') ) created_on = models.DateTimeField(auto_now_add=True, editable=False, verbose_name=_('created on')) modified_on = models.DateTimeField(auto_now=True, editable=False, verbose_name=_('modified on')) identifier = InternalIdentifierField( unique=True, help_text=_('This identifier can be used in templates to create URLs'), editable=True ) visible_in_menu = models.BooleanField(verbose_name=_("visible in menu"), default=False) parent = TreeForeignKey( "self", blank=True, null=True, related_name="children", verbose_name=_("parent")) list_children_on_page = models.BooleanField(verbose_name=_("list children on page"), default=False) translations = TranslatedFields( title=models.CharField(max_length=256, verbose_name=_('title')), url=models.CharField( max_length=100, verbose_name=_('URL'), unique=True, default=None, blank=True, null=True ), content=models.TextField(verbose_name=_('content')), ) objects = TreeManager.from_queryset(PageQuerySet)() class Meta: ordering = ('-id',) verbose_name = _('page') verbose_name_plural = _('pages') def is_visible(self, dt=None): if not dt: dt = now() return ( (self.available_from and self.available_from <= dt) and (self.available_to is None or self.available_to >= dt) ) def get_html(self): return markdown.markdown(self.content) def __str__(self): return force_text(self.safe_translation_getter("title", any_language=True, default=_("Untitled")))
def as_manager(cls): # Address the circular dependency between `Queryset` and `Manager`. from mptt.managers import TreeManager manager = TreeManager.from_queryset(cls)() manager._built_with_as_manager = True return manager
class Category(MPTTModel): name = models.CharField(pgettext_lazy('Category field', 'name'), max_length=128) slug = models.SlugField(pgettext_lazy('Category field', 'slug'), max_length=50) description = models.TextField(pgettext_lazy('Category field', 'description'), blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', verbose_name=pgettext_lazy( 'Category field', 'parent')) hidden = models.BooleanField(pgettext_lazy('Category field', 'hidden'), default=False) seo_keyword = models.CharField(pgettext_lazy('Category field', 'seo keyword'), max_length=128, blank=True, null=True) seo_description = models.CharField(pgettext_lazy('Category field', 'seo description'), max_length=128, blank=True, null=True) objects = models.Manager() tree = TreeManager() class Meta: verbose_name = pgettext_lazy('Category model', 'category') verbose_name_plural = pgettext_lazy('Category model', 'categories') app_label = 'product' def __str__(self): return self.name def get_absolute_url(self, ancestors=None): return reverse('product:category', kwargs={ 'path': self.get_full_path(ancestors), 'category_id': self.id }) def get_full_path(self, ancestors=None): if not self.parent_id: return self.slug if not ancestors: ancestors = self.get_ancestors() nodes = [node for node in ancestors] + [self] return '/'.join([node.slug for node in nodes]) def set_hidden_descendants(self, hidden): self.get_descendants().update(hidden=hidden) def get_visible_children_category(self): return self.get_children().filter(hidden=False)
class AbstractCategory(MPTTModel, AbstractSlug): """ Simple model for categorizing entries. """ title = models.CharField(_('title'), max_length=255) description = models.TextField(_('description'), blank=True) parent = TreeForeignKey('self', related_name='children', null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('parent category')) image = models.ImageField(upload_to=image_upload_to, blank=True, null=True) objects = TreeManager() class Meta: abstract = True class MPTTMeta: """ Category MPTT's meta informations. """ order_insertion_by = ['title'] def __str__(self): return self.title
class Assignment(MPTTModel, TimeStampedModel): parent = TreeForeignKey("self", blank=True, null=True, related_name="children") worksheet = ForeignKey(Worksheet, related_name="assignments") unit = ForeignKey("Unit", related_name="assignments") start = DateTimeField(blank=True, null=True) end = DateTimeField(blank=True, null=True) hide_until_start = BooleanField(default=False) users = ManyToManyField(User, related_name="assignments", through="Engagement") objects = tree = TreeManager() def __unicode__(self): name = "%s assigned for %s %s" % (self.worksheet, self.unit.type, self.unit) if self.start: name += " starting %s" % (self.start) if self.end: name += " until %s" % (self.end) return name
class Category(MPTTModel, TimeStampedModel, SoftDeletableModel): parent = TreeForeignKey('self', null=True, blank=True, verbose_name=_('parent category'), related_name='children', on_delete=models.SET_NULL) name = models.CharField(_('name'), max_length=255, unique=True) cover = models.OneToOneField('covers.Cover', verbose_name=_('cover'), blank=True, null=True, on_delete=models.SET_NULL) slug = models.SlugField(_('slug'), max_length=255, unique=True, allow_unicode=True) description = models.TextField(_('description'), blank=True) objects = TreeManager() public = CategoryManager() class Meta: verbose_name = _('category') verbose_name_plural = _('categories') class MPTTMeta: order_insertion_by = ['-created'] def __str__(self): return self.name
def __new__(meta, class_name, bases, class_dict): """ Create subclasses of MPTTModel. This: - adds the MPTT fields to the class - adds a TreeManager to the model """ mptt_opts = class_dict.pop('MPTTMeta', None) class_dict['_mptt_meta'] = MPTTOptions(mptt_opts) cls = ModelBase.__new__(meta, class_name, bases, class_dict) # For backwards compatibility with existing libraries, we copy the # _mptt_meta options into _meta. # This will be removed in 0.5. # All new code should use _mptt_meta rather than _meta for tree attributes. for attr in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr', 'parent_attr', 'tree_manager_attr', 'order_insertion_by'): setattr(cls._meta, attr, getattr(cls._mptt_meta, attr)) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a custom tree manager manager = TreeManager(cls._mptt_meta) manager.contribute_to_class(cls, cls._mptt_meta.tree_manager_attr) setattr(cls, '_tree_manager', getattr(cls, cls._mptt_meta.tree_manager_attr)) # Set up signal receivers model_signals.post_init.connect(signals.post_init, sender=cls) model_signals.pre_save.connect(signals.pre_save, sender=cls) return cls
class SuperCollection(MPTTModel, SeoModel): parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) collections = models.ManyToManyField('product.Collection', related_name='super_collections', blank=True) name = models.CharField(max_length=128, unique=True) slug = models.SlugField(max_length=128) background_image = VersatileImageField( upload_to='super-collection-backgrounds', blank=True, null=True) is_published = models.BooleanField(default=False) alternative_name = models.CharField(max_length=255, blank=True) content = models.TextField(help_text=pgettext_lazy('Collection extension', 'CMS-able content.'), blank=True) added = models.DateTimeField(auto_now_add=True) objects = SuperCollectionQuerySet.as_manager() tree = TreeManager() class Meta: app_label = 'super_collections' ordering = ['pk'] permissions = (('view', pgettext_lazy('Permission description', 'Can view super collections')), ('edit', pgettext_lazy('Permission description', 'Can edit super collections'))) def __str__(self): return self.name def get_absolute_url(self): return reverse('super-collection-detail', kwargs={ 'pk': self.id, 'slug': self.slug }) def get_full_path(self, ancestors=None): if not self.parent_id: return self.slug if not ancestors: ancestors = self.get_ancestors() nodes = [node for node in ancestors] + [self] return '/'.join([node.slug for node in nodes]) def published_children(self): return self.children.filter(is_published=True) def published_collections(self): return self.collections.filter(is_published=True)
class MultipleManagerModel(MPTTModel): parent = TreeForeignKey( 'self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) published = models.BooleanField() objects = TreeManager() foo_objects = MultipleManager()
class Category(ProductCategoryBase): tree = TreeManager() class Meta: abstract = False app_label = 'shop_categories' verbose_name = _('Product Category') verbose_name_plural = _('Product Categories')
class CategoryBase(MPTTModel): """ This base model includes the absolute bare-bones fields and methods. One could simply subclass this model, do nothing else, and it should work. """ parent = TreeForeignKey( "self", on_delete=models.CASCADE, blank=True, null=True, related_name="children", verbose_name=_("parent"), ) name = models.CharField(max_length=100, verbose_name=_("name")) slug = models.SlugField(verbose_name=_("slug")) active = models.BooleanField(default=True, verbose_name=_("active")) objects = CategoryManager() tree = TreeManager() def save(self, *args, **kwargs): """ Save the category. While you can activate an item without activating its descendants, It doesn't make sense that you can deactivate an item and have its decendants remain active. Args: args: generic args kwargs: generic keyword arguments """ if not self.slug: self.slug = slugify(SLUG_TRANSLITERATOR(self.name))[:50] super(CategoryBase, self).save(*args, **kwargs) if not self.active: for item in self.get_descendants(): if item.active != self.active: item.active = self.active item.save() def __str__(self): ancestors = self.get_ancestors() return " > ".join([force_text(i.name) for i in ancestors] + [ self.name, ]) class Meta: abstract = True unique_together = ("parent", "name") ordering = ("tree_id", "lft") class MPTTMeta: order_insertion_by = "name"
def forwards(self, orm): cls = orm.Party cls._mptt_meta = MPTTOptions(left_attr="tree_left", level_attr="tree_level", right_attr="tree_right") tree_manager = TreeManager() tree_manager.contribute_to_class(cls, "_tree_manager") tree_manager.init_from_model(cls) tree_manager.rebuild()
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError, "register() expects a Django model class argument" if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases)-1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: tree_manager_attr = cls._mptt_meta.tree_manager_attr manager = getattr(cls, tree_manager_attr, None) if (not manager) or manager.model != cls: if not manager: manager = TreeManager() else: # manager.model might already be set if this is a proxy model # (in that case, we need to create a new manager, or _base_manager will be wrong) manager = manager.__class__() manager.contribute_to_class(cls, tree_manager_attr) manager.init_from_model(cls) setattr(cls, '_tree_manager', manager) return cls
def add_root(self, title, **kwargs): menu, created = TreeManager.get_or_create( self, title=title, parent=None, **kwargs ) if not created: raise ValidationError( _('Menu %(name)s already exists'), params={'name': title} ) return menu
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) # For backwards compatibility with existing libraries, we copy the # _mptt_meta options into _meta. # This was removed in 0.5 but added back in 0.5.1 since it caused compatibility # issues with django-cms 2.2.0. # some discussion is here: https://github.com/divio/django-cms/issues/1079 # This stuff is still documented as removed, and WILL be removed again in the next release. # All new code should use _mptt_meta rather than _meta for tree attributes. attrs = set(['left_attr', 'right_attr', 'tree_id_attr', 'level_attr', 'parent_attr', 'tree_manager_attr', 'order_insertion_by']) warned_attrs = set() class _MetaSubClass(cls._meta.__class__): def __getattr__(self, attr): if attr in attrs: if attr not in warned_attrs: warned_attrs.add(attr) return getattr(cls._mptt_meta, attr) return super(_MetaSubClass, self).__getattr__(attr) cls._meta.__class__ = _MetaSubClass try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: manager = getattr(cls, 'objects', None) if manager is None: manager = cls._default_manager._copy_to_model(cls) manager.contribute_to_class(cls, 'objects') elif manager.model != cls: # manager was inherited manager = manager._copy_to_model(cls) manager.contribute_to_class(cls, 'objects') if hasattr(manager, 'init_from_model'): manager.init_from_model(cls) # make sure we have a tree manager somewhere tree_manager = TreeManager() tree_manager.contribute_to_class(cls, '_tree_manager') tree_manager.init_from_model(cls) # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, '_tree_manager', tree_manager) # for backwards compatibility, add .tree too (or whatever's in tree_manager_attr) tree_manager_attr = cls._mptt_meta.tree_manager_attr if tree_manager_attr != 'objects': another = getattr(cls, tree_manager_attr, None) if another is None: # wrap with a warning on first use from django.db.models.manager import ManagerDescriptor class _WarningDescriptor(ManagerDescriptor): def __init__(self, manager): self.manager = manager self.used = False def __get__(self, instance, type=None): if instance != None: raise AttributeError("Manager isn't accessible via %s instances" % type.__name__) if not self.used: self.used = True return self.manager setattr(cls, tree_manager_attr, _WarningDescriptor(manager)) elif hasattr(another, 'init_from_model'): another.init_from_model(cls) return cls
def user_access_filter(self, user): # personal folders filter = Q(owned_by=user) # folders owned by orgs in which the user a member orgs = user.get_orgs() if orgs: filter |= Q(organization__in=orgs) return filter def accessible_to(self, user): return self.filter(self.user_access_filter(user)) FolderManager = TreeManager.from_queryset(FolderQuerySet) class Folder(MPTTModel): name = models.CharField(max_length=255, null=False, blank=False) parent = TreeForeignKey('self', null=True, blank=True, related_name='children') creation_timestamp = models.DateTimeField(auto_now_add=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='folders_created',) # this may be null if this is the shared folder for a org owned_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='folders',) # this will be set if this is inside a shared folder organization = models.ForeignKey(Organization, null=True, blank=True, related_name='folders') # true if this is the apex shared folder (not subfolder) for a org
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: manager = getattr(cls, 'objects', None) if manager is None: manager = cls._default_manager._copy_to_model(cls) manager.contribute_to_class(cls, 'objects') elif manager.model != cls: # manager was inherited manager = manager._copy_to_model(cls) manager.contribute_to_class(cls, 'objects') if hasattr(manager, 'init_from_model'): manager.init_from_model(cls) # make sure we have a tree manager somewhere tree_manager = None for attr in sorted(dir(cls)): try: obj = getattr(cls, attr) except AttributeError: continue if isinstance(obj, TreeManager): tree_manager = obj # prefer any locally defined manager (i.e. keep going if not local) if obj.model is cls: break if tree_manager and tree_manager.model is not cls: tree_manager = tree_manager._copy_to_model(cls) elif tree_manager is None: tree_manager = TreeManager() tree_manager.contribute_to_class(cls, '_tree_manager') tree_manager.init_from_model(cls) # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, '_tree_manager', tree_manager) return cls
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: manager = getattr(cls, 'objects', None) if manager is None: manager = cls._default_manager._copy_to_model(cls) manager.contribute_to_class(cls, 'objects') if hasattr(manager, 'init_from_model'): manager.init_from_model(cls) # make sure we have a tree manager somewhere if not isinstance(manager, TreeManager): manager = TreeManager() manager.contribute_to_class(cls, '_tree_manager') manager.init_from_model(cls) # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, '_tree_manager', manager) # for backwards compatibility, add .tree too (or whatever's in tree_manager_attr) tree_manager_attr = cls._mptt_meta.tree_manager_attr if tree_manager_attr != 'objects': another = getattr(cls, tree_manager_attr, None) if another is None: # wrap with a warning on first use from django.db.models.manager import ManagerDescriptor class _WarningDescriptor(ManagerDescriptor): def __init__(self, manager): self.manager = manager self.used = False def __get__(self, instance, type=None): if instance != None: raise AttributeError("Manager isn't accessible via %s instances" % type.__name__) if not self.used: warnings.warn( 'Implicit manager %s.%s will be removed in django-mptt 0.6. ' ' Explicitly define a TreeManager() on your model to remove this warning.' % (cls.__name__, tree_manager_attr), DeprecationWarning ) self.used = True return self.manager setattr(cls, tree_manager_attr, _WarningDescriptor(manager)) elif hasattr(another, 'init_from_model'): another.init_from_model(cls) return cls
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, "_mptt_meta"): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, "abstract", False) # For backwards compatibility with existing libraries, we copy the # _mptt_meta options into _meta. # This was removed in 0.5 but added back in 0.5.1 since it caused compatibility # issues with django-cms 2.2.0. # some discussion is here: https://github.com/divio/django-cms/issues/1079 # This stuff is still documented as removed, and WILL be removed again in the next release. # All new code should use _mptt_meta rather than _meta for tree attributes. attrs = ( "left_attr", "right_attr", "tree_id_attr", "level_attr", "parent_attr", "tree_manager_attr", "order_insertion_by", ) warned_attrs = set() class _MetaSubClass(cls._meta.__class__): def __getattr__(self, attr): if attr in attrs: if attr not in warned_attrs: warnings.warn( "%s._meta.%s is deprecated and will be removed in mptt 0.6" % (cls.__name__, attr), # don't use DeprecationWarning, that gets ignored by default UserWarning, ) warned_attrs.add(attr) return getattr(cls._mptt_meta, attr) return super(_MetaSubClass, self).__getattr__(attr) cls._meta.__class__ = _MetaSubClass try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in xrange(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) for key in ("left_attr", "right_attr", "tree_id_attr", "level_attr"): field_name = getattr(cls._mptt_meta, key) try: cls._meta.get_field(field_name) except models.FieldDoesNotExist: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: manager = getattr(cls, "objects", None) if manager is None: manager = cls._default_manager._copy_to_model(cls) manager.contribute_to_class(cls, "objects") elif manager.model != cls: # manager was inherited manager = manager._copy_to_model(cls) manager.contribute_to_class(cls, "objects") if hasattr(manager, "init_from_model"): manager.init_from_model(cls) # make sure we have a tree manager somewhere tree_manager = None for attr in sorted(dir(cls)): try: obj = getattr(cls, attr) except AttributeError: continue if isinstance(obj, TreeManager): tree_manager = obj # prefer any locally defined manager (i.e. keep going if not local) if obj.model is cls: break if tree_manager and tree_manager.model is not cls: tree_manager = tree_manager._copy_to_model(cls) elif tree_manager is None: tree_manager = TreeManager() tree_manager.contribute_to_class(cls, "_tree_manager") tree_manager.init_from_model(cls) # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, "_tree_manager", tree_manager) return cls
for menu in MenuItem.objects.all(): cache.delete('menu-%s' % menu.slug) cache.delete('menu-tree-%s' % menu.slug) class MenuUnCacheQuerySet(TreeQuerySet): def delete(self, *args, **kwargs): delete_cache() super(MenuUnCacheQuerySet, self).delete(*args, **kwargs) def update(self, *args, **kwargs): delete_cache() super(MenuUnCacheQuerySet, self).update(*args, **kwargs) MenuItemManager = TreeManager.from_queryset(MenuUnCacheQuerySet) class MenuItem(MPTTModel): parent = TreeForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) label = models.CharField( _('label'), max_length=255, help_text="The display name on the web site.", ) slug = models.SlugField( _('slug'), unique=True, max_length=255,
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, '_mptt_meta'): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, 'abstract', False) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) if _get_tree_model(cls) is cls: # HACK: _meta.get_field() doesn't work before AppCache.ready in Django>=1.8 # ( see https://code.djangoproject.com/ticket/24231 ) # So the only way to get existing fields is using local_fields on all superclasses. existing_field_names = set() for base in cls.mro(): if hasattr(base, '_meta'): existing_field_names.update([f.name for f in base._meta.local_fields]) for key in ('left_attr', 'right_attr', 'tree_id_attr', 'level_attr'): field_name = getattr(cls._mptt_meta, key) if field_name not in existing_field_names: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: # make sure we have a tree manager somewhere tree_manager = None if hasattr(cls._meta, 'concrete_managers'): # Django < 1.10 cls_managers = cls._meta.concrete_managers + cls._meta.abstract_managers cls_managers = [r[2] for r in cls_managers] else: cls_managers = cls._meta.managers for cls_manager in cls_managers: if isinstance(cls_manager, TreeManager): # prefer any locally defined manager (i.e. keep going if not local) if cls_manager.model is cls: tree_manager = cls_manager break if tree_manager and tree_manager.model is not cls: tree_manager = tree_manager._copy_to_model(cls) elif tree_manager is None: tree_manager = TreeManager() tree_manager.contribute_to_class(cls, '_tree_manager') # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, '_tree_manager', tree_manager) return cls
def register(meta, cls, **kwargs): """ For the weird cases when you need to add tree-ness to an *existing* class. For other cases you should subclass MPTTModel instead of calling this. """ if not issubclass(cls, models.Model): raise ValueError(_("register() expects a Django model class argument")) if not hasattr(cls, "_mptt_meta"): cls._mptt_meta = MPTTOptions(**kwargs) abstract = getattr(cls._meta, "abstract", False) try: MPTTModel except NameError: # We're defining the base class right now, so don't do anything # We only want to add this stuff to the subclasses. # (Otherwise if field names are customized, we'll end up adding two # copies) pass else: if not issubclass(cls, MPTTModel): bases = list(cls.__bases__) # strip out bases that are strict superclasses of MPTTModel. # (i.e. Model, object) # this helps linearize the type hierarchy if possible for i in range(len(bases) - 1, -1, -1): if issubclass(MPTTModel, bases[i]): del bases[i] bases.insert(0, MPTTModel) cls.__bases__ = tuple(bases) if _get_tree_model(cls) is cls: # HACK: _meta.get_field() doesn't work before AppCache.ready in Django>=1.8 # ( see https://code.djangoproject.com/ticket/24231 ) # So the only way to get existing fields is using local_fields on all superclasses. existing_field_names = set() for base in cls.mro(): if hasattr(base, "_meta"): existing_field_names.update([f.name for f in base._meta.local_fields]) for key in ("left_attr", "right_attr", "tree_id_attr", "level_attr"): field_name = getattr(cls._mptt_meta, key) if field_name not in existing_field_names: field = models.PositiveIntegerField(db_index=True, editable=False) field.contribute_to_class(cls, field_name) # Add a tree manager, if there isn't one already if not abstract: manager = getattr(cls, "objects", None) if manager is None: manager = cls._default_manager._copy_to_model(cls) manager.contribute_to_class(cls, "objects") elif manager.model != cls: # manager was inherited manager = manager._copy_to_model(cls) manager.contribute_to_class(cls, "objects") # make sure we have a tree manager somewhere tree_manager = None attrs = dir(cls) if "objects" in attrs and isinstance(cls.objects, TreeManager): tree_manager = cls.objects # Go look for it somewhere else else: for attr in sorted(attrs): try: # HACK: avoid using getattr(cls, attr) # because it calls __get__ on descriptors, which can cause nasty side effects # with more inconsiderate apps. # (e.g. django-tagging's TagField is a descriptor which can do db queries on getattr) # ( ref: http://stackoverflow.com/questions/27790344 ) obj = cls.__dict__[attr] except KeyError: continue if isinstance(obj, TreeManager): tree_manager = obj # prefer any locally defined manager (i.e. keep going if not local) if obj.model is cls: break if tree_manager and tree_manager.model is not cls: tree_manager = tree_manager._copy_to_model(cls) elif tree_manager is None: tree_manager = TreeManager() tree_manager.contribute_to_class(cls, "_tree_manager") # avoid using ManagerDescriptor, so instances can refer to self._tree_manager setattr(cls, "_tree_manager", tree_manager) return cls