示例#1
0
def make_breadcrumb(byurls, path):
    """
    Breadcrumb generation

    Takes a reverse-sorted list of URLs, and find the most specific
    URL for the requested path. E.g if the path is /a/b/c/ and the menu
    has two items /a/ and /a/b/ then /a/b/ will be chosen). Once the most
    specific item is chosen, it gets the corresponding menu item and
    follow it's parents to the root.

    It is imperative that the byurls is reverse-sorted for this
    breadcrumb generation to work as expected.
    """
    if path == '/':
        return []

    if settings.USE_I18N:
        lang = translation.get_language()

    for url, val in byurls:
        if settings.USE_I18N:
            url = get_path_for_language(lang, url)
        if path.startswith(url) and url != '/' and url != '':
            crumb = []
            while val:
                if 'hide_menu_root' in val and val['hide_menu_root']:
                    break
                if settings.USE_I18N:
                    crumb.append({
                        'title':
                        val['title'],
                        'link':
                        get_path_for_language(lang, val['link']),
                        'on_click':
                        val['on_click']
                    })
                else:
                    crumb.append({
                        'title': val['title'],
                        'link': val['link'],
                        'on_click': val['on_click']
                    })
                val = val['parent']
            crumb.reverse()
            return crumb

    return None
def url_for_lang(path, lang):
    '''
    Return the url for the given languge
    e.g.: /public/ (de) -> /public/germany/
    '''

    # Get the "original" path in case we're dealing with a translated path
    path = get_language_from_path(path)[2]

    return get_path_for_language(lang, path)
示例#3
0
    def process_response(self, request, response):
        if not settings.USE_I18N:
            return super(DjangoplicityRedirectFallbackMiddleware,
                         self).process_response(request, response)

        if response.status_code != 404:
            return response  # No need to check for a redirect for non-404 responses.

        full_path = request.get_full_path()
        current_site = get_current_site(request)

        r = None
        try:
            r = Redirect.objects.get(site=current_site, old_path=full_path)
        except Redirect.DoesNotExist:
            pass

        if not r:
            # Let's check if the current path is a local (translated) path
            # and whether we have a redirect for the original path
            lang, dummy_prefix, original_path = get_language_from_path(
                full_path)

            if full_path != original_path:
                try:
                    r = Redirect.objects.get(site=current_site,
                                             old_path=original_path)

                    # We update the Redirects' new_path with the prefix of the
                    # current language to prevent another redirect round trip
                    # later on but we don't save it
                    r.new_path = get_path_for_language(lang, r.new_path)
                except Redirect.DoesNotExist:
                    pass

        if settings.APPEND_SLASH and not request.path.endswith('/'):
            # Try appending a trailing slash.
            path_len = len(request.path)
            full_path = full_path[:path_len] + '/' + full_path[path_len:]
            try:
                r = Redirect.objects.get(site=current_site, old_path=full_path)
            except Redirect.DoesNotExist:
                pass

        if r is not None:
            if r.new_path == '':
                return http.HttpResponseGone()
            return http.HttpResponsePermanentRedirect(r.new_path)

        # No redirect was found. Return the response.
        return response
示例#4
0
    def process_view( self, request, view_func, view_args, view_kwargs ):
        """
        We have three kind of paths:
            1. Fully translated path and models (Translate: True)
            2. Translated path, but page itself is not translated (Translate: False)
            3. No translation at all (default) (no Translate kwarg)

        In case 1. and 2. we make sure that the correct URL is being accessed
        otherwise we redirect
        """
        if settings.USE_I18N and not _is_just_media(request.path):
            preferred_language = request.PREFERRED_LANGUAGE

            # We translate all pages except if they are explicitely disabled
            # e.g. for djangoplicity.archives.contrib.security.views.serve_static_file

            if 'translate' in view_kwargs:
                translate = view_kwargs['translate']
                del view_kwargs['translate']

                # If the path language is different than the preferred one
                # we redirect to the preferred language version
                if request.PATH_LANGUAGE != preferred_language:
                    path = request.path_info
                    querystring = get_querystring_from_request(request)

                    if querystring:
                        # Add query string to redirect path if any
                        path += '?' + querystring

                    return redirect(get_path_for_language(preferred_language, path))

                if not translate:
                    # The URL is not translated, so we set a variable that can
                    # be used to display a message in the template if the
                    # default language is not in the same family as the current
                    # preferred language
                    if not preferred_language.startswith(settings.LANGUAGE_CODE):
                        request.NO_TRANSLATION = True
                    translate = True
示例#5
0
def view_page(request, url):
    """
    View for rendering pages. The view can either be called through
    the PageFallbackMiddleware or add the following line as the last entry
    in urls.py (a catch all pattern):

    {{{
        ( r'^(?P<url>.*)', iaumemberdb.views.test_view )
    }}}

    The difference between the middleware and the URL matching method, is that
    the with the URL method it wall always be this view that returns a 404
    response, while with the fallback middleware, the middleware will return the
    original 404 response in case no page was found.

    The view has the following features:
    * Authentication::
        * Staff users with pages.can_view_inactive permissions can see all pages
        (inactive as well as login protected)
        * Pages can be require login/authentication
    * Caching::
        * For static pages the entire HTML document is cached.
        * For dynamic pages the compiled template is cached.
    * Dynamic content::
        * By default only MEDIA_URL is available as variable, beside the normal
        template markup.
    * Pages can be embedded cannot be viewed through this view, but should
        use the embed_page view.
    * URL lookup is done through a cached URL index, if possible.
    """
    if not url.startswith('/'):
        url = "/" + url

    if settings.USE_I18N:
        lang = translation.get_language()
    else:
        lang = None

    # Generate cache key
    if request.user.is_staff and request.user.has_perm(
            'pages.can_view_inactive') and 'preview' in request.GET:
        # We don't cache if user has permissions and in preview mode
        cache_key = None
    else:
        cache_key = '%s_%s' % (CACHE_KEY['pages'], str(url.__hash__()))
        if lang:
            cache_key += '_%s' % lang

        if is_internal(request):
            cache_key += '_internal'
        else:
            cache_key += '_external'

    if cache_key:
        page_cache = cache.get(cache_key)
    else:
        page_cache = None

    if page_cache is not None:
        page = page_cache['page']
    else:
        # Use precompiled index of urls for the site.
        index = cache.get(CACHE_KEY['urlindex'])
        if index is None:
            index = build_urlindex()

        if url in index:
            page = Page.objects.get(embedded__exact=0, pk=index[url])
        elif settings.USE_I18N and request.path in index:
            # If we use translations let's check if the page exists with a full
            # URL, e.g.: /public/chile/about-eso/
            page = Page.objects.filter(embedded__exact=0,
                                       pk=index[request.path]).get()
        else:
            # If the URL doesn't exist let's check if it does exist with
            # a trailing /
            if not url.endswith('/') and url + '/' in index:
                return redirect(request.path + '/')

            raise Http404

        # The current preferred language is different than the page's,
        # If the page was not originally accessed through the "translated"
        # URL then we redirect the user:
        language_path = get_path_for_language(lang, request.path_info)

        if request.path != language_path:
            querystring = get_querystring_from_request(request)

            if querystring:
                # Add query string to redirect path if any
                language_path += '?' + querystring

            return redirect(language_path)

        if settings.USE_I18N and lang != page.lang:
            # Next we check if we have a translation for the page, in which
            # case we use it, othewise we use the original version but set
            # a variable to be used in the template
            try:
                trans = page.translations.get(lang=lang)
                if trans.published and trans.translation_ready:
                    page = trans
                else:
                    request.NO_TRANSLATION = True
            except Page.DoesNotExist:
                # There are not translations in the preferred language, next we
                # check if the source is in the same language family, if not
                # we display a sorry message
                if lang[:2] != page.lang[:2]:
                    request.NO_TRANSLATION = True

    # Page Protection
    # ---------------
    # Authentication and active pages.
    #  - Staff users with 'pages.can_view_inactive' permissions can view pages online
    #    even if they are inactive (this is a preview functionality).
    try:
        _authorize_pageview(request, page)
    except PageNotFoundError:
        raise Http404
    except PageAuthorizationError:
        from django.contrib.auth.views import redirect_to_login
        return redirect_to_login(request.path)

    # If the page has a redirect_url set we return a HTTP 301 permanent redirection
    if page.redirect_url:
        return HttpResponsePermanentRedirect(page.redirect_url)

    #
    # Rendering
    #
    htmlkey = 'html%s' % '-admin' if request.user.is_superuser else ''
    ctpl = None

    # We don't want to cache the page with the link to the admin page
    # so if the user has edit access we don't use the cache
    if page_cache is not None and not request.user.has_perm(
            'pages.change_page'):
        # Cache
        if htmlkey in page_cache:
            # We already have a fully rendered page so return it.
            return HttpResponse(page_cache[htmlkey])
        elif 'template' in page_cache:
            # We only have a compiled template, so we need to render the page
            ctpl = page_cache['template']

    if ctpl is None:
        # No cache
        ctpl = engines['django'].from_string(page.content)

    # Render content
    page.title = mark_safe(page.title)
    page.content = mark_safe(ctpl.render({}, request))

    # Render entire page
    template_names = (page.template_name, page.section.template)
    template = select_template([x for x in template_names if x])
    html = template.render(
        {
            'page':
            page,
            'translations':
            page.get_translations(),
            'admin_edit':
            admin_edit_for_site('admin_site',
                                translation_proxy=PageProxy)(page),
        }, request)

    # Cache page (either entire page, or only compiled content template)
    # Note: Inactive pages and pages viewed by users with admin access
    # are never cached
    if cache_key:
        if page.is_online() and not request.user.has_perm('pages.change_page'):
            if page.dynamic and page_cache is None:
                cache.set(cache_key, {'page': page, 'template': ctpl})
            else:
                if not page_cache:
                    page_cache = {'page': page}

                page_cache[htmlkey] = html
                cache.set(cache_key, page_cache)

    return HttpResponse(html)