Example #1
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        if len(model._feincms_templates) > 4 and \
                'template_key' in self.radio_fields:
            del(self.radio_fields['template_key'])

        super(PageAdmin, self).__init__(model, admin_site)

        # The use of fieldsets makes only fields explicitly listed in there
        # actually appear in the admin form. However, extensions should not be
        # aware that there is a fieldsets structure and even less modify it;
        # we therefore enumerate all of the model's field and forcibly add them
        # to the last section in the admin. That way, nobody is left behind.
        from django.contrib.admin.util import flatten_fieldsets
        present_fields = flatten_fieldsets(self.fieldsets)

        for f in self.model._meta.fields:
            if (not f.name.startswith('_')
                    and not f.name in ('id', 'lft', 'rght', 'tree_id', 'level')
                    and not f.auto_created
                    and not f.name in present_fields
                    and f.editable):
                self.fieldsets[1][1]['fields'].append(f.name)
                warnings.warn(
                    'Automatically adding %r to %r.fieldsets. This behavior'
                    ' is deprecated. Use add_extension_options yourself if'
                    ' you want fields to appear in the page'
                    ' administration.' % (f.name, self.__class__),
                    DeprecationWarning)
            if not f.editable:
                self.readonly_fields.append(f.name)
Example #2
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        if len(model._feincms_templates) > 4 and "template_key" in self.radio_fields:
            del (self.radio_fields["template_key"])

        super(PageAdmin, self).__init__(model, admin_site)
Example #3
0
    def __init__(self, *args, **kwargs):
        ensure_completely_loaded()

        if len(Page._feincms_templates) > 4 and "template_key" in self.radio_fields:
            del (self.radio_fields["template_key"])

        super(PageAdmin, self).__init__(*args, **kwargs)

        # The use of fieldsets makes only fields explicitly listed in there
        # actually appear in the admin form. However, extensions should not be
        # aware that there is a fieldsets structure and even less modify it;
        # we therefore enumerate all of the model's field and forcibly add them
        # to the last section in the admin. That way, nobody is left behind.
        from django.contrib.admin.util import flatten_fieldsets

        present_fields = flatten_fieldsets(self.fieldsets)

        for f in self.model._meta.fields:
            if (
                not f.name.startswith("_")
                and not f.name in ("id", "lft", "rght", "tree_id", "level")
                and not f.auto_created
                and not f.name in present_fields
                and f.editable
            ):
                self.unknown_fields.append(f.name)
                if not f.editable:
                    self.readonly_fields.append(f.name)
Example #4
0
    def __init__(self, *args, **kwargs):
        ensure_completely_loaded()

        if 'initial' in kwargs:
            if 'parent' in kwargs['initial']:
                # Prefill a few form values from the parent page
                try:
                    page = Page.objects.get(pk=kwargs['initial']['parent'])
                    data = model_to_dict(page)

                    for field in PageManager.exclude_from_copy:
                        if field in data:
                            del data[field]

                    # These are always excluded from prefilling
                    for field in self.never_copy_fields:
                        if field in data:
                            del data[field]

                    kwargs['initial'].update(data)
                except Page.DoesNotExist:
                    pass

            elif 'translation_of' in kwargs['initial']:
                # Only if translation extension is active
                try:
                    page = Page.objects.get(pk=kwargs['initial']['translation_of'])
                    original = page.original_translation

                    data = {
                        'translation_of': original.id,
                        'template_key': original.template_key,
                        'active': original.active,
                        'in_navigation': original.in_navigation,
                        }

                    if original.parent:
                        try:
                            data['parent'] = original.parent.get_translation(kwargs['initial']['language']).id
                        except Page.DoesNotExist:
                            # ignore this -- the translation does not exist
                            pass

                    kwargs['initial'].update(data)
                except Page.DoesNotExist:
                    pass

        super(PageAdminForm, self).__init__(*args, **kwargs)
        if 'instance' in kwargs:
            choices = []
            for key, template in kwargs['instance'].TEMPLATE_CHOICES:
                template = kwargs['instance']._feincms_templates[key]
                if template.preview_image:
                    choices.append((template.key,
                                    mark_safe(u'<img src="%s" alt="%s" /> %s' % (
                                              template.preview_image, template.key, template.title))))
                else:
                    choices.append((template.key, template.title))

            self.fields['template_key'].choices = choices
Example #5
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        if len(model._feincms_templates) > 4 and "template_key" in self.radio_fields:
            del self.radio_fields["template_key"]

        super(PageAdmin, self).__init__(model, admin_site)
Example #6
0
        def _needs_content_types(cls):
            ensure_completely_loaded()

            # Check whether any content types have been created for this base class
            if not hasattr(cls, '_feincms_content_types'
                           ) or not cls._feincms_content_types:
                raise ImproperlyConfigured, 'You need to create at least one content type for the %s model.' % (
                    cls.__name__)
Example #7
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        if len(model._feincms_templates) > 4 and \
                'template_key' in self.radio_fields:
            del (self.radio_fields['template_key'])

        super(PostAdmin, self).__init__(model, admin_site)
Example #8
0
        def _needs_templates(cls):
            ensure_completely_loaded()

            # helper which can be used to ensure that either register_regions or
            # register_templates has been executed before proceeding
            if not hasattr(cls, 'template'):
                raise ImproperlyConfigured, 'You need to register at least one template or one region on %s.' % (
                    cls.__name__, )
Example #9
0
        def _needs_content_types(cls):
            ensure_completely_loaded()

            # Check whether any content types have been created for this base class
            if not hasattr(cls, "_feincms_content_types") or not cls._feincms_content_types:
                raise ImproperlyConfigured, "You need to create at least one content type for the %s model." % (
                    cls.__name__
                )
Example #10
0
        def _needs_templates(cls):
            ensure_completely_loaded()

            # helper which can be used to ensure that either register_regions
            # or register_templates has been executed before proceeding
            if not hasattr(cls, 'template'):
                raise ImproperlyConfigured('You need to register at least one'
                    ' template or one region on %s.' % cls.__name__)
Example #11
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)

        # Add inline instances for FeinCMS content inlines
        for inline_class in get_feincms_inlines(model):
            inline_instance = inline_class(self.model, self.admin_site)
            self.inline_instances.append(inline_instance)
Example #12
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)

        # Add inline instances for FeinCMS content inlines
        for inline_class in self.get_feincms_inlines(model):
            inline_instance = inline_class(self.model, self.admin_site)
            self.inline_instances.append(inline_instance)
Example #13
0
        def _needs_content_types(cls):
            ensure_completely_loaded()

            # Check whether any content types have been created for this base
            # class
            if (not hasattr(cls, '_feincms_content_types')
                    or not cls._feincms_content_types):
                raise ImproperlyConfigured('You need to create at least one'
                    ' content type for the %s model.' % cls.__name__)
Example #14
0
        def _needs_content_types(cls):
            ensure_completely_loaded()

            # Check whether any content types have been created for this base
            # class
            if not getattr(cls, '_feincms_content_types', None):
                raise ImproperlyConfigured('You need to create at least one'
                                           ' content type for the %s model.' %
                                           cls.__name__)
Example #15
0
                def _template(self):
                    ensure_completely_loaded()

                    try:
                        return self._feincms_templates[self.template_key]
                    except KeyError:
                        # return first template as a fallback if the template
                        # has changed in-between
                        return self._feincms_templates[self._feincms_templates.keys()[0]]
Example #16
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)

        if hasattr(self, 'inline_instances'):
            # Add inline instances for FeinCMS content inlines
            # This works in Django 1.3 and lower
            # In Django 1.4 inline instances are generated using overridden get_inline_instances()
            self.append_feincms_inlines(self.inline_instances)
Example #17
0
        def _needs_content_types(cls):
            ensure_completely_loaded()

            # Check whether any content types have been created for this base
            # class
            if not getattr(cls, "_feincms_content_types", None):
                raise ImproperlyConfigured(
                    "You need to create at least one"
                    " content type for the %s model." % cls.__name__
                )
Example #18
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)

        if hasattr(self, 'inline_instances'):
            # Add inline instances for FeinCMS content inlines
            # This works in Django 1.3 and lower
            # In Django 1.4 inline instances are generated using overridden get_inline_instances()
            self.append_feincms_inlines(self.inline_instances)
Example #19
0
                def _template(self):
                    ensure_completely_loaded()

                    try:
                        return self._feincms_templates[self.template_key]
                    except KeyError:
                        # return first template as a fallback if the template
                        # has changed in-between
                        return self._feincms_templates[
                            list(self._feincms_templates.keys())[0]]
Example #20
0
    def __init__(self, *args, **kwargs):
        ensure_completely_loaded()

        if len(Page._feincms_templates) > 4 and 'template_key' in self.radio_fields:
            del(self.radio_fields['template_key'])

        super(PageAdmin, self).__init__(*args, **kwargs)

        # The use of fieldsets makes only fields explicitly listed in there
        # actually appear in the admin form. However, extensions should not be
        # aware that there is a fieldsets structure and even less modify it;
        # we therefore enumerate all of the model's field and forcibly add them
        # to the last section in the admin. That way, nobody is left behind.
        from django.contrib.admin.util import flatten_fieldsets
        present_fields = flatten_fieldsets(self.fieldsets)

        for f in self.model._meta.fields:
            if not f.name.startswith('_') and not f.name in ('id', 'lft', 'rght', 'tree_id', 'level') and \
                    not f.auto_created and not f.name in present_fields and f.editable:
                self.unknown_fields.append(f.name)
            if not f.editable:
                self.readonly_fields.append(f.name)
Example #21
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 #22
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)
Example #23
0
    def __init__(self, *args, **kwargs):
        ensure_completely_loaded()

        if 'initial' in kwargs:
            if 'parent' in kwargs['initial']:
                # Prefill a few form values from the parent page
                try:
                    page = self.page_manager.get(
                        pk=kwargs['initial']['parent'])

                    data = model_to_dict(page)

                    for field in self.page_manager.exclude_from_copy:
                        if field in data:
                            del data[field]

                    # These are always excluded from prefilling
                    for field in self.never_copy_fields:
                        if field in data:
                            del data[field]

                    data.update(kwargs['initial'])
                    if page.template.child_template:
                        data['template_key'] = page.template.child_template
                    kwargs['initial'] = data
                except self.page_model.DoesNotExist:
                    pass

            elif 'translation_of' in kwargs['initial']:
                # Only if translation extension is active
                try:
                    page = self.page_manager.get(
                        pk=kwargs['initial']['translation_of'])
                    original = page.original_translation

                    data = {
                        'translation_of': original.id,
                        'template_key': original.template_key,
                        'active': original.active,
                        'in_navigation': original.in_navigation,
                    }

                    if original.parent:
                        try:
                            data['parent'] = original.parent.get_translation(
                                kwargs['initial']['language']
                            ).id
                        except self.page_model.DoesNotExist:
                            # ignore this -- the translation does not exist
                            pass

                    data.update(kwargs['initial'])
                    kwargs['initial'] = data
                except (AttributeError, self.page_model.DoesNotExist):
                    pass

        # Not required, only a nice-to-have for the `redirect_to` field
        modeladmin = kwargs.pop('modeladmin', None)
        super(PageAdminForm, self).__init__(*args, **kwargs)
        if modeladmin and 'redirect_to' in self.fields:
            # Note: Using `parent` is not strictly correct, but we can be
            # sure that `parent` always points to another page instance,
            # and that's good enough for us.
            self.fields['redirect_to'].widget = RedirectToWidget(
                self.page_model._meta.get_field('parent').rel,
                modeladmin.admin_site)

        if 'template_key' in self.fields:
            choices = []
            for key, template_name in self.page_model.TEMPLATE_CHOICES:
                template = self.page_model._feincms_templates[key]
                pages_for_template = self.page_model._default_manager.filter(
                    template_key=key)
                pk = kwargs['instance'].pk if kwargs.get('instance') else None
                other_pages_for_template = pages_for_template.exclude(pk=pk)
                if template.singleton and other_pages_for_template.exists():
                    continue  # don't allow selection of singleton if in use
                if template.preview_image:
                    choices.append((
                        template.key,
                        mark_safe('<img src="%s" alt="%s" /> %s' % (
                            template.preview_image,
                            template.key,
                            template.title,
                        ))
                    ))
                else:
                    choices.append((template.key, template.title))

            self.fields['template_key'].choices = choices
Example #24
0
# ------------------------------------------------------------------------

from __future__ import absolute_import, unicode_literals

from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured
from django.db.models import FieldDoesNotExist

from feincms import ensure_completely_loaded, settings
from .models import Page
from .modeladmins import PageAdmin

# ------------------------------------------------------------------------

if settings.FEINCMS_USE_PAGE_ADMIN:
    ensure_completely_loaded()
    try:
        Page._meta.get_field('template_key')
    except FieldDoesNotExist:
        raise ImproperlyConfigured(
            "The page module requires a 'Page.register_templates()' call "
            "somewhere ('Page.register_regions()' is not sufficient). "
            "If you're not using the default Page admin, maybe try "
            "FEINCMS_USE_PAGE_ADMIN=False to avoid this warning."
        )

    admin.site.register(Page, PageAdmin)

# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
Example #25
0
    def __init__(self, *args, **kwargs):
        ensure_completely_loaded()

        if "initial" in kwargs:
            if "parent" in kwargs["initial"]:
                # Prefill a few form values from the parent page
                try:
                    page = Page.objects.get(pk=kwargs["initial"]["parent"])
                    data = model_to_dict(page)

                    for field in PageManager.exclude_from_copy:
                        if field in data:
                            del data[field]

                    # These are always excluded from prefilling
                    for field in self.never_copy_fields:
                        if field in data:
                            del data[field]

                    data.update(kwargs["initial"])
                    kwargs["initial"] = data
                except Page.DoesNotExist:
                    pass

            elif "translation_of" in kwargs["initial"]:
                # Only if translation extension is active
                try:
                    page = Page.objects.get(pk=kwargs["initial"]["translation_of"])
                    original = page.original_translation

                    data = {
                        "translation_of": original.id,
                        "template_key": original.template_key,
                        "active": original.active,
                        "in_navigation": original.in_navigation,
                    }

                    if original.parent:
                        try:
                            data["parent"] = original.parent.get_translation(kwargs["initial"]["language"]).id
                        except Page.DoesNotExist:
                            # ignore this -- the translation does not exist
                            pass

                    data.update(kwargs["initial"])
                    kwargs["initial"] = data
                except (AttributeError, Page.DoesNotExist):
                    pass

        super(PageAdminForm, self).__init__(*args, **kwargs)
        if "instance" in kwargs:
            choices = []
            for key, template in kwargs["instance"].TEMPLATE_CHOICES:
                template = kwargs["instance"]._feincms_templates[key]
                if template.preview_image:
                    choices.append(
                        (
                            template.key,
                            mark_safe(
                                u'<img src="%s" alt="%s" /> %s' % (template.preview_image, template.key, template.title)
                            ),
                        )
                    )
                else:
                    choices.append((template.key, template.title))

            self.fields["template_key"].choices = choices
Example #26
0
# coding=utf-8
# ------------------------------------------------------------------------

from __future__ import absolute_import

from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured
from django.db.models import FieldDoesNotExist

from feincms import ensure_completely_loaded, settings
from .models import Page
from .modeladmins import PageAdmin

# ------------------------------------------------------------------------

if settings.FEINCMS_USE_PAGE_ADMIN:
    ensure_completely_loaded()
    try:
        Page._meta.get_field('template_key')
    except FieldDoesNotExist:
        raise ImproperlyConfigured(
            "The page module requires a 'Page.register_templates()' call "
            "somewhere ('Page.register_regions()' is not sufficient). "
            "If you're not using the default Page admin, maybe try "
            "FEINCMS_USE_PAGE_ADMIN=False to avoid this warning.")

    admin.site.register(Page, PageAdmin)

# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
Example #27
0
    def __init__(self, model, admin_site):
        ensure_completely_loaded()

        super(ItemEditor, self).__init__(model, admin_site)