예제 #1
0
    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
예제 #2
0
파일: models.py 프로젝트: sf-thelab/saleor
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
예제 #3
0
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
예제 #4
0
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()}
예제 #5
0
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])
예제 #6
0
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
예제 #7
0
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
                       })
예제 #8
0
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)
예제 #9
0
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
예제 #10
0
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()
예제 #11
0
파일: models.py 프로젝트: timotsang/saleor
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])
예제 #12
0
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, ))
예제 #13
0
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
예제 #14
0
class BaseTermManager(RebuildTreeMixin,
                      TreeManager.from_queryset(BaseTermQuerySet)):
    """
    ENG: Customized model manager for our Term model.
    RUS: Адаптированная модель менеджера для модели Терминов.
    """
    '''
예제 #15
0
파일: models.py 프로젝트: ronreiter/saleor
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
                       })
예제 #16
0
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']
예제 #17
0
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)
예제 #18
0
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
예제 #19
0
파일: models.py 프로젝트: harry81/iclover
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
예제 #20
0
파일: models.py 프로젝트: sreeni90/saleor
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 ""
예제 #21
0
파일: base.py 프로젝트: mjroson/saleor
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)
예제 #22
0
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")))
예제 #23
0
    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
예제 #24
0
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)
예제 #25
0
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
예제 #26
0
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
예제 #27
0
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
예제 #28
0
    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
예제 #29
0
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)
예제 #30
0
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()
예제 #31
0
class Category(ProductCategoryBase):
    tree = TreeManager()

    class Meta:
        abstract = False
        app_label = 'shop_categories'
        verbose_name = _('Product Category')
        verbose_name_plural = _('Product Categories')
예제 #32
0
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"
예제 #33
0
    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()
예제 #34
0
    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
예제 #35
0
 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
예제 #36
0
    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
예제 #37
0
    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
예제 #38
0
    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
예제 #39
0
파일: models.py 프로젝트: zeus/django-mptt
    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
예제 #40
0
    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
예제 #41
0
    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,
예제 #42
0
    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
예제 #43
0
    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