Example #1
0
    def get_redirect_to_target(self, request):
        """
        This might be overriden/extended by extension modules.
        """

        if not self.redirect_to:
            return ''

        # It might be an identifier for a different object
        match = REDIRECT_TO_RE.match(self.redirect_to)

        # It's not, oh well.
        if not match:
            return self.redirect_to

        matches = match.groupdict()
        model = get_model(matches['app_label'], matches['model_name'])

        if not model:
            return self.redirect_to

        try:
            instance = model._default_manager.get(pk=int(matches['pk']))
            return instance.get_absolute_url()
        except models.ObjectDoesNotExist:
            pass

        return self.redirect_to
Example #2
0
    def __init__(self, navigation_only=False, max_depth=0, changefreq=None,
                 queryset=None, filter=None, extended_navigation=False,
                 page_model=settings.FEINCMS_DEFAULT_PAGE_MODEL,
                 *args, **kwargs):
        """
        The PageSitemap accepts the following parameters for customisation
        of the resulting sitemap.xml output:

        * navigation_only -- if set to True, only pages that are in_navigation
        will appear in the site map.
        * max_depth -- if set to a non-negative integer, will limit the sitemap
        generated to this page hierarchy depth.
        * changefreq -- should be a string or callable specifiying the page
        update frequency, according to the sitemap protocol.
        * queryset -- pass in a query set to restrict the Pages to include
        in the site map.
        * filter -- pass in a callable that transforms a queryset to filter
        out the pages you want to include in the site map.
        * extended_navigation -- if set to True, adds pages from any navigation
        extensions. If using PagePretender, make sure to include title, url,
        level, in_navigation and optionally modification_date.
        """
        super(PageSitemap, self).__init__(*args, **kwargs)
        self.depth_cutoff = max_depth
        self.navigation_only = navigation_only
        self.changefreq = changefreq
        self.filter = filter
        self.extended_navigation = extended_navigation
        if queryset is not None:
            self.queryset = queryset
        else:
            Page = get_model(*page_model.split('.'))
            self.queryset = Page.objects.active()
Example #3
0
    def get_redirect_to_page(self):
        """
        This might be overriden/extended by extension modules.
        """

        if not self.redirect_to:
            return None

        # It might be an identifier for a different object
        match = REDIRECT_TO_RE.match(self.redirect_to)

        # It's not, oh well.
        if not match:
            return None

        matches = match.groupdict()
        model = get_model(matches['app_label'], matches['model_name'])

        if not model:
            return None

        try:
            instance = model._default_manager.get(pk=int(matches['pk']))
            return instance
        except models.ObjectDoesNotExist:
            pass

        return None
Example #4
0
    def label_for_value(self, value):
        match = re.match(
            # XXX this regex would be available as .models.REDIRECT_TO_RE
            r'^(?P<app_label>\w+).(?P<model_name>\w+):(?P<pk>\d+)$',
            value)

        if match:
            matches = match.groupdict()
            model = get_model(matches['app_label'], matches['model_name'])
            try:
                instance = model._default_manager.get(pk=int(matches['pk']))
                return '&nbsp;<strong>%s (%s)</strong>' % (
                    instance, instance.get_absolute_url())

            except model.DoesNotExist:
                pass

        return ''
Example #5
0
def get_singleton(template_key, cls=None, raise_exception=True):
    cls = cls or settings.FEINCMS_DEFAULT_PAGE_MODEL
    try:
        model = get_model(*cls.split('.'))
        if not model:
            raise ImproperlyConfigured('Cannot load model "%s"' % cls)
        try:
            assert model._feincms_templates[template_key].singleton
        except AttributeError as e:
            raise ImproperlyConfigured(
                '%r does not seem to be a valid FeinCMS base class (%r)' % (
                    model,
                    e,
                )
            )
        except KeyError:
            raise ImproperlyConfigured(
                '%r is not a registered template for %r!' % (
                    template_key,
                    model,
                )
            )
        except AssertionError:
            raise ImproperlyConfigured(
                '%r is not a *singleton* template for %r!' % (
                    template_key,
                    model,
                )
            )
        try:
            return model._default_manager.get(template_key=template_key)
        except model.DoesNotExist:
            raise  # not yet created?
        except model.MultipleObjectsReturned:
            raise  # hmm, not exactly a singleton...
    except Exception:
        if raise_exception:
            raise
        else:
            return None
Example #6
0
    def __init__(self,
                 navigation_only=False,
                 max_depth=0,
                 changefreq=None,
                 queryset=None,
                 filter=None,
                 extended_navigation=False,
                 page_model=settings.FEINCMS_DEFAULT_PAGE_MODEL,
                 *args,
                 **kwargs):
        """
        The PageSitemap accepts the following parameters for customisation
        of the resulting sitemap.xml output:

        * navigation_only -- if set to True, only pages that are in_navigation
        will appear in the site map.
        * max_depth -- if set to a non-negative integer, will limit the sitemap
        generated to this page hierarchy depth.
        * changefreq -- should be a string or callable specifiying the page
        update frequency, according to the sitemap protocol.
        * queryset -- pass in a query set to restrict the Pages to include
        in the site map.
        * filter -- pass in a callable that transforms a queryset to filter
        out the pages you want to include in the site map.
        * extended_navigation -- if set to True, adds pages from any navigation
        extensions. If using PagePretender, make sure to include title, url,
        level, in_navigation and optionally modification_date.
        """
        super(PageSitemap, self).__init__(*args, **kwargs)
        self.depth_cutoff = max_depth
        self.navigation_only = navigation_only
        self.changefreq = changefreq
        self.filter = filter
        self.extended_navigation = extended_navigation
        if queryset is not None:
            self.queryset = queryset
        else:
            Page = get_model(*page_model.split('.'))
            self.queryset = Page.objects.active()
Example #7
0
def get_singleton(template_key, cls=None, raise_exception=True):
    cls = cls or settings.FEINCMS_DEFAULT_PAGE_MODEL
    try:
        model = get_model(*cls.split('.'))
        if not model:
            raise ImproperlyConfigured('Cannot load model "%s"' % cls)
        try:
            assert model._feincms_templates[template_key].singleton
        except AttributeError as e:
            raise ImproperlyConfigured(
                '%r does not seem to be a valid FeinCMS base class (%r)' % (
                    model,
                    e,
                ))
        except KeyError:
            raise ImproperlyConfigured(
                '%r is not a registered template for %r!' % (
                    template_key,
                    model,
                ))
        except AssertionError:
            raise ImproperlyConfigured(
                '%r is not a *singleton* template for %r!' % (
                    template_key,
                    model,
                ))
        try:
            return model._default_manager.get(template_key=template_key)
        except model.DoesNotExist:
            raise  # not yet created?
        except model.MultipleObjectsReturned:
            raise  # hmm, not exactly a singleton...
    except Exception:
        if raise_exception:
            raise
        else:
            return None
Example #8
0
        def create_content_type(cls, model, regions=None, class_name=None,
                                **kwargs):
            """
            This is the method you'll use to create concrete content types.

            If the CMS base class is ``page.models.Page``, its database table
            will be ``page_page``. A concrete content type which is created
            from ``ImageContent`` will use ``page_page_imagecontent`` as its
            table.

            If you want a content type only available in a subset of regions,
            you can pass a list/tuple of region keys as ``regions``. The
            content type will only appear in the corresponding tabs in the item
            editor.

            If you use two content types with the same name in the same module,
            name clashes will happen and the content type created first will
            shadow all subsequent content types. You can work around it by
            specifying the content type class name using the ``class_name``
            argument. Please note that this will have an effect on the entries
            in ``django_content_type``, on ``related_name`` and on the table
            name used and should therefore not be changed after running
            ``syncdb`` for the first time.

            Name clashes will also happen if a content type has defined a
            relationship and you try to register that content type to more than
            one Base model (in different modules).  Django will raise an error
            when it tries to create the backward relationship. The solution to
            that problem is, as shown above, to specify the content type class
            name with the ``class_name`` argument.

            If you register a content type to more than one Base class, it is
            recommended to always specify a ``class_name`` when registering it
            a second time.

            You can pass additional keyword arguments to this factory function.
            These keyword arguments will be passed on to the concrete content
            type, provided that it has a ``initialize_type`` classmethod. This
            is used f.e. in ``MediaFileContent`` to pass a set of possible
            media positions (f.e. left, right, centered) through to the content
            type.
            """

            if not class_name:
                class_name = model.__name__

            # prevent double registration and registration of two different
            # content types with the same class name because of related_name
            # clashes
            try:
                getattr(cls, '%s_set' % class_name.lower())
                warnings.warn(
                    'Cannot create content type using %s.%s for %s.%s,'
                    ' because %s_set is already taken.' % (
                        model.__module__, class_name,
                        cls.__module__, cls.__name__,
                        class_name.lower()),
                    RuntimeWarning)
                return
            except AttributeError:
                # everything ok
                pass

            if django.VERSION < (1, 7):
                # Next name clash test. Happens when the same content type is
                # created for two Base subclasses living in the same Django
                # application (github issues #73 and #150)
                #
                # FIXME This code does not work with Django 1.7, because
                # get_model depends on the app cache which is not ready at
                # this time yet.
                try:
                    other_model = get_model(cls._meta.app_label, class_name)
                    if other_model is None:
                        # Django 1.6 and earlier
                        raise LookupError
                except LookupError:
                    pass
                else:
                    warnings.warn(
                        'It seems that the content type %s exists twice in %s.'
                        ' Use the class_name argument to create_content_type'
                        ' to avoid this error.' % (
                            model.__name__,
                            cls._meta.app_label),
                        RuntimeWarning)

            if not model._meta.abstract:
                raise ImproperlyConfigured(
                    'Cannot create content type from'
                    ' non-abstract model (yet).')

            if not hasattr(cls, '_feincms_content_model'):
                cls._create_content_base()

            feincms_content_base = cls._feincms_content_model

            class Meta(feincms_content_base.Meta):
                db_table = '%s_%s' % (cls._meta.db_table, class_name.lower())
                verbose_name = model._meta.verbose_name
                verbose_name_plural = model._meta.verbose_name_plural
                permissions = model._meta.permissions

            attrs = {
                # put the concrete content type into the
                # same module as the CMS base type; this is
                # necessary because 1. Django needs to know
                # the module where a model lives and 2. a
                # content type may be used by several CMS
                # base models at the same time (f.e. in
                # the blog and the page module).
                '__module__': cls.__module__,
                'Meta': Meta,
            }

            new_type = type(
                str(class_name),
                (model, feincms_content_base,),
                attrs,
            )
            cls._feincms_content_types.append(new_type)

            if hasattr(getattr(new_type, 'process', None), '__call__'):
                cls._feincms_content_types_with_process.append(new_type)
            if hasattr(getattr(new_type, 'finalize', None), '__call__'):
                cls._feincms_content_types_with_finalize.append(new_type)

            # content types can be limited to a subset of regions
            if not regions:
                regions = set([
                    region.key for region in cls._feincms_all_regions])

            for region in cls._feincms_all_regions:
                if region.key in regions:
                    region._content_types.append(new_type)

            # Add a list of CMS base types for which a concrete content type
            # has been created to the abstract content type. This is needed
            # f.e. for the update_rsscontent management command, which needs to
            # find all concrete RSSContent types, so that the RSS feeds can be
            # fetched
            if not hasattr(model, '_feincms_content_models'):
                model._feincms_content_models = []

            model._feincms_content_models.append(new_type)

            # Add a backlink from content-type to content holder class
            new_type._feincms_content_class = cls

            # Handle optgroup argument for grouping content types in the item
            # editor
            optgroup = kwargs.pop('optgroup', None)
            if optgroup:
                new_type.optgroup = optgroup

            # customization hook.
            if hasattr(new_type, 'initialize_type'):
                new_type.initialize_type(**kwargs)
            else:
                for k, v in kwargs.items():
                    setattr(new_type, k, v)

            # collect item editor context processors from the content type
            if hasattr(model, 'feincms_item_editor_context_processors'):
                cls.feincms_item_editor_context_processors.extend(
                    model.feincms_item_editor_context_processors)

            # collect item editor includes from the content type
            if hasattr(model, 'feincms_item_editor_includes'):
                for key, incls in model.feincms_item_editor_includes.items():
                    cls.feincms_item_editor_includes.setdefault(
                        key, set()).update(incls)

            ensure_completely_loaded(force=True)
            return new_type
Example #9
0
 def page_model(self):
     model = self.page_model_path or settings.FEINCMS_DEFAULT_PAGE_MODEL
     return get_model(*model.split('.'))
Example #10
0
    def handle_ajax_method(self, request, method):
        """handle ajax methods and return serialized reponse
        in the default state allows only authentificated users

        - Depends on method parameter render whole region or single widget

        - If widget_id is present then try to load this widget
          and call method on them

        - If class_name is present then try to load class
          and then call static method on this class

        - If class_name is present then try to load class
          and if method_name == render_preview then
          render widget preview without instance

        """

        response = {}

        def get_param(request, name):

            try:
                return request.POST[name]
            except KeyError:
                return request.GET.get(name, None)

        widget_id = get_param(request, "widget_id")
        class_name = get_param(request, "class_name")

        if method in 'widget_content':
            return self.render_widget(request, widget_id)

        if method == 'region':
            return self.render_region(request)

        # handle methods called directly on widget
        if widget_id:

            widget = get_widget_from_id(widget_id)

            try:
                func = getattr(widget, method)
            except AttributeError:
                response["exception"] = "%s method is not implmented on %s" % (
                    method, widget)
            else:
                response["result"] = func(request)

        elif class_name:
            # handle calling classmethod without instance

            try:
                cls = get_model(*class_name.split('.'))
            except Exception as e:
                response["exception"] = str(e)
                return JsonResponse(data=response)

            if method == "render_preview":

                # TODO: i think that we need only simple form
                # for loading relations but maybe this would be need it
                # custom_form_cls = getattr(
                #     cls, 'feincms_item_editor_form', None)

                # if custom_form_cls:
                #     FormCls = modelform_factory(cls, form=custom_form_cls,
                #                                 exclude=('pk', 'id'))

                FormCls = modelform_factory(cls, exclude=('pk', 'id'))

                form = FormCls(request.POST)

                if form.is_valid():

                    widget = cls(**form.cleaned_data)

                    request.frontend_editing = False

                    content = widget.render(**{'request': request})

                    response['result'] = content
                    response['id'] = widget_id

                else:
                    response['result'] = form.errors
                    response['id'] = widget_id

            else:
                # standard method
                try:
                    func = getattr(cls, method)
                except Exception as e:
                    response["exception"] = str(e)
                else:
                    response["result"] = func(request)

        return JsonResponse(data=response)
Example #11
0
 def page_model(self):
     model = self.page_model_path or settings.FEINCMS_DEFAULT_PAGE_MODEL
     return get_model(*model.split('.'))
Example #12
0
def _get_page_model():
    return get_model(*feincms_settings.FEINCMS_DEFAULT_PAGE_MODEL.split('.'))
def _get_page_model():
    return get_model(*feincms_settings.FEINCMS_DEFAULT_PAGE_MODEL.split('.'))