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
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()
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
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 ' <strong>%s (%s)</strong>' % ( instance, instance.get_absolute_url()) except model.DoesNotExist: pass return ''
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
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
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
def page_model(self): model = self.page_model_path or settings.FEINCMS_DEFAULT_PAGE_MODEL return get_model(*model.split('.'))
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)
def _get_page_model(): return get_model(*feincms_settings.FEINCMS_DEFAULT_PAGE_MODEL.split('.'))