Пример #1
0
    def __init__(self, *args, **kwargs):
        super(DirectoryBackendSection, self).__init__(*args, **kwargs)

        # tags
        self.sections = [DirectoryTagsSection()]

        # categories
        category_models = []
        for model in get_models():
            if issubclass(model, DirectoryCategory):
                category_models.append(model)
        category_models.sort(key=lambda m: m.__name__)
        self.sections.extend([DirectoryCategorySection(m) for m in category_models])

        # directory entities
        content_models = []
        for model in get_models():
            if issubclass(model, DirectoryEntity):
                content_models.append(model)
        for title, attr, value, model in self.get_model_sections(content_models):
            slug = slugify(title)
            _title = get_listing_option(model, 'title')
            if _title is not None:
                title = _title
            self.sections.append(DirectoryContentSubSection(title, slug, attr, value, model, model.get_backend_section_group()))

        # sort sections by title
        self.sections.sort(key=lambda s: s.title)
Пример #2
0
    def handle(self, *args, **options):
        """
        Run command.
        """
        print 'Rewriting CMS links ...Please Wait...'

        # simulation mode?
        simulate = options.get('simulate', False)

        # collect content models
        cms = get_cms()
        cms_models = tuple(cms.get_supported_models())
        links = self.get_page_links()

        # process all models in the system
        models = get_models()
        i = 0
        n = 0
        for m in models:
            if issubclass(m, cms_models):
                _i, _n = self.process_model(m, links, simulate,
                                            options.get('pk'))
                i += _i
                n += _n

        print '%d item(s) updated out of %d content page(s) in total.%s' % (
            i, n, ' (Simulated!)' if simulate else '')
Пример #3
0
    def configure(self, request, instance=None, edit=True):
        super(PageForm, self).configure(request, instance, edit)

        # generate list of entity type choices based on all django models
        # that subclass from PageBase (but not Page itself).
        choices = [('', '-------')]
        for model in get_models():
            if issubclass(model, ChildPage):
                choices.append((model.__name__, model._meta.verbose_name))
        self.fields['entity_type'].choices = choices

        # navigation
        if edit or self.is_duplicate:
            self.fields['nav'].initial = instance.nav

        # parent page only available if hierarchical pages is enabled
        if not settings.PAGE_HIERARCHY:
            self.remove_field('parent')
            self.update_sections()

        # 404 page cannot be disabled!
        cms_settings = get_cms_settings()
        if instance and cms_settings.default_404 and instance.pk == cms_settings.default_404.pk:
            self.fields['disabled'].widget.attrs['disabled'] = True
            self.fields[
                'disabled'].help_text = 'This page is configured as the default 404 (Page Not Found) page and can therefore not be disabled.'
            self.fields['sitemap'].widget.attrs['disabled'] = True
            self.fields[
                'sitemap'].help_text = 'This page is configured as the default 404 (Page Not Found) page and can therefore not be excluded from the sitemap.'
Пример #4
0
def get_directory_content_backend_sections(backend_section):
    """
    Return a list of all backend sections that are related to directory content.
    """
    # append all known directory content entities and categories
    sections = []
    content_models = []
    for model in get_models():
        if issubclass(model, DirectoryContentBase) or issubclass(model, DirectoryContentEntity):
            content_models.append(model)

    # create sections
    sections = []
    for title, attr, value, model in backend_section.get_model_sections(content_models):
        slug = slugify(title)
        _title = get_listing_option(model, 'title')
        if _title is not None:
            title = _title

        if attr and value and hasattr(model, 'get_backend_section_title'):
            title = model.get_backend_section_title(value)

        sections.append(DirectoryContentSubSection(title, slug, attr, value, model, model.get_backend_section_group()))

    return sections
Пример #5
0
 def delete_directory_categories(self):
     """
     Delete all directory categories.
     """
     for model in get_models():
         if issubclass(model, DirectoryCategory):
             for c in model.objects.all():
                 c.delete()
Пример #6
0
 def delete_entities(self):
     """
     Delete all cms entities.
     """
     for model in get_models():
         if issubclass(model, Entity):
             for page in model.objects.all():
                 page.delete()
Пример #7
0
 def delete_child_pages(self):
     """
     Delete all child pages.
     """
     for model in get_models():
         if issubclass(model, ChildPage):
             for page in model.objects.all():
                 page.delete()
Пример #8
0
 def get_directory_models(self):
     """
     Return a list of aggregate-able directory content asset models.
     """
     models = []
     for model in get_models():
         if issubclass(model, DirectoryContentBase):
             models.append(model)
     return models
Пример #9
0
 def get_directory_category_models(self):
     """
     Return a list of models representing directory categories.
     """
     models = []
     for model in get_models():
         if issubclass(model, DirectoryCategory):
             models.append(model)
     return models
Пример #10
0
def get_child_page_models():
    """
    Return a list of all models that are derived from ChildPage.
    """
    _models = []
    for model in get_models():
        if issubclass(model, ChildPage):
            _models.append(model)
    return _models
Пример #11
0
    def save(self, *args, **kwargs):
        try:
            old_title = DirectoryTag.objects.get(pk=self.pk).title
        except:
            old_title = None

        for model in get_models():
            self.update_tags_for_model(model, old_title, self.title)

        super(DirectoryTag, self).save(*args, **kwargs)
Пример #12
0
    def _get_model_by_table_name(self, table):
        """
        Return the model based on the given table name.
        """
        if not hasattr(self, '_model_table_cache'):
            self._model_table_cache = {}
            for model in get_models():
                self._model_table_cache[model._meta.db_table] = model

        return self._model_table_cache.get(table)
Пример #13
0
 def delete_entities(self):
     """
     Override: Deleting all CMS entities but NOT directory entities.
     """
     for model in get_models():
         if (issubclass(model, Entity) and not issubclass(
                 model, DirectoryContentEntity)) or issubclass(
                     model, DirectoryEntity):
             for page in model.objects.all():
                 page.delete()
Пример #14
0
 def delete_directory_content_pages(self):
     """
     Delete all directory content pages.
     """
     for model in get_models():
         if issubclass(model, DirectoryContentBase) or issubclass(
                 model, DirectoryContentEntity) or issubclass(
                     model, DirectoryEntity):
             for page in model.objects.all():
                 page.delete()
Пример #15
0
    def get_sitemaps(self):
        """
        Override: Add directory-specific content to sitemap.
        """
        _sitemaps = super(CMSExtensions, self).get_sitemaps()

        # directory content
        for model in get_models():
            if issubclass(model, DirectoryContentBase):
                _sitemaps[slugify(model._meta.verbose_name)] = CMSDirectoryContentSitemap(self, model)

        return _sitemaps
Пример #16
0
    def node(self, request):
        # get cms
        from cubane.cms.views import get_cms
        cms = get_cms()

        # root level (pages and directory categories)
        if 'pk' not in request.GET and 'type' not in request.GET:
            return to_json_response({
                'success': True,
                'items': [cms.get_sitemap_item(request, page) for page in cms.get_sitemap_root_pages()]
            })

        # get pk argument
        if 'pk' not in request.GET:
            raise Http404('Missing argument: pk.')
        try:
            pk = int(request.GET.get('pk'))
        except ValueError:
            raise Http404('Invalid pk argument: Not a number.')

        # get type argument
        if 'type' not in request.GET:
            raise Http404('Missing argument: type.')
        type_name = request.GET.get('type')

        # resolve type by given name
        model = None
        for m in get_models():
            if m.__name__ == type_name:
                model = m
                break
        if not model:
            raise Http404('Unknown model type name: \'%s\'.' % type_name)

        # get node by given pk
        node = model.objects.get(pk=pk)

        # generate child nodes
        items = []
        children = cms.get_sitemap_children(node)
        if children:
            for child in children:
                item = cms.get_sitemap_item(request, child)
                if item:
                    items.append(item)

        # return response (json)
        return to_json_response({
            'success': True,
            'items': items
        })
Пример #17
0
    def get_entity_model(self):
        """
        Return the entity model that this page manages.
        """
        if self._entity_model == None:
            self._entity_model = False
            for model in get_models():
                if model.__name__ == self.entity_type:
                    self._entity_model = model
                    break

        if self._entity_model:
            return self._entity_model
        else:
            return None
Пример #18
0
 def get_page_links(self):
     """
     Return a dictionary of all known content pages via their url path.
     """
     result = {}
     cms = get_cms()
     cms_models = tuple(cms.get_supported_models())
     models = get_models()
     for model in models:
         if issubclass(model, cms_models):
             for instance in model.objects.all():
                 if hasattr(instance, 'get_absolute_url'):
                     page_path = to_legacy_url(instance.get_absolute_url())
                     link = '#link[%s:%s]' % (model.__name__, instance.pk)
                     result[page_path] = link
     return result
Пример #19
0
    def get_object_model(self, model_name):
        """
        Create a object model with given name.
        """
        # only consider the axtual name
        if '.' in model_name:
            model_name = model_name.split('.')[-1]

        supported_models = self.get_supported_models()
        for model in get_models():
            valid = False
            for supported_model in supported_models:
                if issubclass(model, supported_model):
                    if model_name == model.__name__:
                        return model
        return None
Пример #20
0
def load_model_fixtures(connection, stdout=sys.stdout, verbosity=1):
    """
    Load the initial data for all models as defined for each model.
    """
    for model in get_models():
        fixtures = get_model_fixtures(model)
        if len(fixtures) > 0:
            if verbosity >= 1:
                for fixture in fixtures:
                    stdout.write('Loading initial data fixture: %s.\n' %
                                 fixture)
            args = ['loaddata'] + fixtures
            call_command(*args,
                         interactive=False,
                         database=connection.alias,
                         run_syncdb=True,
                         verbosity=verbosity)
Пример #21
0
    def _add_related_log(self, instance):
        """
        Recursively issue change log entries for related items that are pointing
        to instance but would be set to NULL due to deleting instance.
        """
        # find all models that are holding a reference to the given instance
        # model, which might be one of the following
        # - ForeignKey to instance model
        # - OneToOneField to instance model
        # - ManyToManyField without a through model referencing instance model
        # - GenericRelation.
        # ManyToManyField with a though model are irrelevant, since they will
        # be found because of a ForeignKey that exists to the instance model
        # in the intermediate model class.
        for model in get_models():
            # skip self or ChangeLog
            if model == instance.__class__ or model == ChangeLog:
                continue

            # scan for related fields that are referencing the instance model
            for field in model._meta.get_fields():
                # only RelatedField
                if not isinstance(field, RelatedField):
                    continue

                # ignore ManyToMany or GenericRelation
                if field.many_to_many or isinstance(field, GenericRelation):
                    continue

                # ignore the ones that are not pointing to instance model
                if not issubclass(instance.__class__, field.rel.model):
                    continue

                # get affected target objects
                objects = model.objects.filter(**{field.name: instance.pk})

                # generate log entry
                for obj in objects:
                    if field.null:
                        # nullable field -> log edit
                        previous_obj = self.get_changes(obj)
                        setattr(obj, field.attname, None)
                        self.edit(obj, previous_obj)
                    else:
                        # not nullable -> log delete
                        self.delete(obj)
Пример #22
0
    def __init__(self, *args, **kwargs):
        super(ShopBackendSection, self).__init__(*args, **kwargs)

        # finance options
        if settings.SHOP_LOAN_ENABLED:
            from cubane.ishop.apps.merchant.finance.views import FinanceOptionBackendSection
            self.sections.append(FinanceOptionBackendSection())

        # append all known shop entities
        entity_models = []
        for model in get_models():
            if issubclass(model, ShopEntity):
                entity_models.append(model)

        # sort by name
        entity_models = sorted(entity_models, key=lambda m: m.__name__)

        # create sections
        self.sections.extend([ShopContentEntitySection(model, model.get_backend_section_group()) for model in entity_models])
Пример #23
0
    def get_changes(self, a, b=None):
        """
        Return a structure in JSON that describes the changes that occurred for
        the given model a (before the change) and b (after the change).
        """
        # nothing to work with
        if a is None and b is None:
            return None

        # identify model class and get list of known models
        _class = a.__class__
        models = get_models()

        # identify all database columns from model
        fieldnames = get_model_field_names(_class)

        # generate index over b (if available)
        index = {}
        if b is not None:
            for entry in b:
                index[entry.get('n')] = entry.get('a')

        def _array_equal(ass, bss):
            if len(ass) != len(bss):
                return False

            for i, a in enumerate(ass):
                if a != bss[i]:
                    return False

            return True

        # generate changes
        result = []
        for fieldname in fieldnames:
            # get field is model
            field = _class._meta.get_field(fieldname)

            # ignore file fields
            if isinstance(field, DjangoFileField):
                continue

            # get previous value (b)
            if b is not None:
                vb = index.get(field.attname)
            else:
                vb = None

            # get current and previous values
            if field.many_to_many:
                # ignore ManyToMany with through model. It will be picked up
                # by collecting related objects
                has_through_model = False
                for m in models:
                    if issubclass(field.rel.through, m):
                        has_through_model = True
                        break
                if has_through_model:
                    continue

                # get list of pk's for many-to-many related objects
                if a.pk:
                    va = getattr(a, field.name)
                    if va is not None: va = [x.pk for x in va.all()]
                else:
                    va = []
            else:
                va = getattr(a, field.attname)

            # value changed?
            changed = False
            if b is not None:
                if isinstance(va, list) and isinstance(vb, list):
                    changed = not _array_equal(va, vb)
                else:
                    changed = va != vb

            if b is None or changed:
                result.append({'n': field.attname, 'a': va, 'b': vb})
        return result
Пример #24
0
# coding=UTF-8
from __future__ import unicode_literals
from django.conf.urls import url
from cubane.directory.models import DirectoryContentBase
from cubane.lib.app import get_models
from cubane.directory import views

# dispatch directory content
urls = []
for model in get_models():
    if issubclass(model, DirectoryContentBase):
        ctypes = model.get_directory_content_type_slugs()
        for attr_name, backend_section, ct in ctypes:
            p = r'^' + ct + r'/(?P<slug>[-\w\d]+)-(?P<pk>\d+)/$'
            urls.append(
                url(p,
                    views.content,
                    kwargs={
                        'model': model,
                        'attr_name': attr_name,
                        'backend_section': backend_section
                    },
                    name='cubane.directory.content.%s' % ct))

# url patterns
urlpatterns = urls
Пример #25
0
def auto_migrate(interactive=True, load_fixtures=True, verbose=True):
    """
    Automatically migrate current schema.
    """
    # get database schema manager and start transaction, so that we can confirm
    # all changes at the end...
    schema = get_schema(connection, verbose)
    schema.begin()

    # lock all tables, so that we have exclusive access to the schema and data
    schema.lock(get_models())

    # create/rename tables
    models_visited = []
    for model in get_models():
        create_or_rename_table(schema, model, interactive, models_visited)

    # update tables
    for model in get_models():
        schema.update_table(model)

    # list containing custom indices that will be checked for existence and
    # created if not present.
    from django.contrib.contenttypes.models import ContentType
    custom_index = {
        get_class_name_with_modules(ContentType):
        ['app_label', 'model', ['app_label', 'model']]
    }

    # apply custom indecies not defined in the model, for example adding
    # index to auth_user's email address...
    indicies = []
    for model in get_models():
        indicies.extend(check_custom_indexing(schema, model, custom_index))
    schema.keep_indicies(indicies)

    # migrate schema for each table
    fts_reindex_models = []
    for model in get_models():
        create_or_rename_fields(schema, model, interactive)
        drop_deprecated_fields(schema, model)
        update_fields(schema, model)
        if fts_install_for_model(schema, model):
            fts_reindex_models.append(model)

    # migrate content types
    schema.migrate_django_content_types()

    # ask user if he realy wants to go ahead with these changes...
    if ask_confirm("Apply changes?", interactive):
        commit_changes(schema)

        # ask for fts reindex if required
        if len(fts_reindex_models) > 0:
            if ask_confirm(
                    "One or more models changed regarding full text search. Do you want to re-index now?",
                    interactive):
                for model in fts_reindex_models:
                    schema.fts_reindex_model(model)

        # re-install fixtures
        if load_fixtures:
            load_model_fixtures(connection, verbosity=1 if interactive else 0)
    else:
        schema.rollback()
Пример #26
0
    def get_aggregated_pages(self, include_tags, exclude_tags=[], order=DirectoryOrder.ORDER_DEFAULT, max_items=None, navigation=False, visibility_filter_args={}):
        """
        Return a list of all aggregated pages for the given include tags and exclude tags
        ordered by the given order. If no order is given, the system-wide order applies
        (settings). The number of result records may be limited to the number given.
        If the navigation argument is True, then directory content entities are NOT
        included in the result set.
        """
        # enfore list of list of tags for include tags
        include_tags = list_of_list(include_tags)
        exclude_tags = list_of(exclude_tags)

        # create cache
        if not hasattr(self, '_agg_cache'):
            self._agg_cache = {}

        # collect all aggregated content
        pages = []
        el_tags = set()
        for model in get_models():
            if issubclass(model, DirectoryContentBase) or (not navigation and issubclass(model, DirectoryContentEntity)):
                # create cache key
                cache_id = '%s-%s-%d-%s' % (
                    '-'.join(itertools.chain(*include_tags)),
                    '-'.join(exclude_tags),
                    order,
                    model
                )

                # deliver partial result from cache?
                if cache_id in self._agg_cache:
                    agg_pages = self._agg_cache[cache_id]
                else:
                    agg_pages = self._agg_cache[cache_id] = model.objects.filter_by_tags(include_tags, exclude_tags, visibility_filter_args)

                # if the page is an aggregator as well as directory content,
                # then collect cascading tags to eliminate content
                if issubclass(model, DirectoryContentAndAggregator):
                    for p in agg_pages:
                        el_tags |= p.get_cascading_tags()

                pages.extend(agg_pages)

        # eliminate all pages that match one of the cascading tags found...
        if len(el_tags) > 0:
            pages = filter(lambda p: not p.matches_tags(el_tags), pages)

        # default order from settings?
        if order == DirectoryOrder.ORDER_DEFAULT:
            order = self.settings.order_mode

        # order pages
        if order == DirectoryOrder.ORDER_RANDOM:
            # seed random number generator based on the week and year, so that
            # we get a different random order every week but the order stays the
            # same during the week...
            now = datetime.now()
            random.seed('%s/%s' % (now.year, now.isocalendar()[1]))

            # generate and inject a random seq...
            for p in pages:
                p._random_seq = random.randint(0, 65535)

            # sort by random seq
            pages.sort(key=lambda x: x._random_seq)
        elif order == DirectoryOrder.ORDER_SEQ:
            pages.sort(key=lambda x: x.seq)
        elif order == DirectoryOrder.ORDER_TITLE:
            pages.sort(key=lambda x: x.title if hasattr(x, 'title') else False)
        elif order == DirectoryOrder.ORDER_DATE:
            pages.sort(key=lambda x: x.created_on, reverse=True)
        elif order == DirectoryOrder.ORDER_CUSTOM_DATE:
            pages.sort(key=lambda x: (x.custom_date or dt.datetime(1970, 1, 1)), reverse=False)

        # sort by priority
        pages.sort(key=lambda x: not x.priority)

        # move items with top priority to the top of the listing
        pages.sort(key=lambda x: not x.top_priority)

        # restrict the maximum number of aggregated items
        if max_items != None:
            pages = pages[:max_items]

        return pages
Пример #27
0
 def fts_reindex(self):
     """
     Reindex full text search index for all models with full text search index.
     """
     for model in get_models():
         self.fts_reindex_model(model)
Пример #28
0
 def delete(self):
     super(DirectoryTag, self).delete()
     for model in get_models():
         self.remove_tags_from_model(model, self.title)