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)
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
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
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)