PageSitemap   A
last analyzed

Complexity

Total Complexity 2

Size/Duplication

Total Lines 11
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 2
dl 0
loc 11
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A lastmod() 0 2 1
A items() 0 2 1
1
"""Default example views"""
2
from pages import settings
3
from pages.models import Page, PageAlias
4
from pages.phttp import get_language_from_request, remove_slug
5
from pages.urlconf_registry import get_urlconf
6
from pages.utils import get_placeholders
7
8
from django.http import Http404, HttpResponsePermanentRedirect
9
from django.contrib.sitemaps import Sitemap
10
from django.core.urlresolvers import resolve, Resolver404
11
from django.utils import translation
12
from django.shortcuts import render
13
14
LANGUAGE_KEYS = [key for (key, value) in settings.PAGE_LANGUAGES]
15
16
17
class Details(object):
18
    """
19
    This class based view get the root pages for navigation
20
    and the current page to display if there is any.
21
22
    All is rendered with the current page's template.
23
    """
24
25
    def __call__(
26
            self, request, path=None, lang=None, delegation=True,
27
            **kwargs):
28
29
        current_page = False
30
31
        if path is None:
32
            raise ValueError(
33
                "pages.views.Details class view requires the path argument. "
34
                "Check your urls.py file.")
35
36
        # for the ones that might have forgotten to pass the language
37
        # the language is now removed from the page path
38
        if settings.PAGE_USE_LANGUAGE_PREFIX and lang is None:
39
            maybe_lang = path.split("/")[0]
40
            if maybe_lang in LANGUAGE_KEYS:
41
                lang = maybe_lang
42
                path = path[(len(lang) + 1):]
43
44
        lang = self.choose_language(lang, request)
45
        pages_navigation = self.get_navigation(request, path, lang)
46
47
        context = {
48
            'path': path,
49
            'pages_navigation': pages_navigation,
50
            'lang': lang,
51
        }
52
53
        is_staff = self.is_user_staff(request)
54
55
        current_page = self.resolve_page(request, context, is_staff)
56
57
        # Do redirect to new page (if enabled)
58
        if settings.PAGE_REDIRECT_OLD_SLUG and current_page:
59
            url = current_page.get_absolute_url(language=lang)
60
            slug = current_page.get_complete_slug(language=lang)
61
            current_url = request.get_full_path()
62
            if url != path and url + '/' != current_url and slug != path:
63
                return HttpResponsePermanentRedirect(url)
64
65
        # if no pages has been found, we will try to find it via an Alias
66
        if not current_page:
67
            redirection = self.resolve_alias(request, path, lang)
68
            if redirection:
69
                return redirection
70
        else:
71
            context['current_page'] = current_page
72
73
        # If unauthorized to see the pages, raise a 404, That can
74
        # happen with expired pages.
75
        if not is_staff and not current_page.visible:
76
            raise Http404
77
78
        redirection = self.resolve_redirection(request, context)
79
        if redirection:
80
            return redirection
81
82
        self.extra_context(request, context)
83
84
        if delegation and current_page.delegate_to:
85
            answer = self.delegate(request, context, delegation, **kwargs)
86
            if answer:
87
                return answer
88
89
        if kwargs.get('only_context', False):
90
            return context
91
        template_name = kwargs.get(
92
            'template_name',
93
            self.get_template(request, context))
94
95
        context['template_name'] = template_name
96
97
        return render(request, template_name, context)
98
99
    def resolve_page(self, request, context, is_staff):
100
        """Return the appropriate page according to the path."""
101
        path = context['path']
102
        lang = context['lang']
103
        page = Page.objects.from_path(
104
            path, lang,
105
            exclude_drafts=(not is_staff))
106
        if page:
107
            return page
108
        # if the complete path didn't worked out properly
109
        # and if didn't used PAGE_USE_STRICT_URL setting we gonna
110
        # try to see if it might be a delegation page.
111
        # To do that we remove the right part of the url and try again
112
        # to find a page that match
113
        if not settings.PAGE_USE_STRICT_URL:
114
            path = remove_slug(path)
115
            while path is not None:
116
                page = Page.objects.from_path(
117
                    path, lang,
118
                    exclude_drafts=(not is_staff))
119
                # find a match. Is the page delegating?
120
                if page:
121
                    if page.delegate_to:
122
                        return page
123
                path = remove_slug(path)
124
125
        return None
126
127
    def resolve_alias(self, request, path, lang):
128
        alias = PageAlias.objects.from_path(request, path, lang)
129
        if alias:
130
            url = alias.page.get_url_path(lang)
131
            return HttpResponsePermanentRedirect(url)
132
        raise Http404
133
134
    def resolve_redirection(self, request, context):
135
        """Check for redirections."""
136
        current_page = context['current_page']
137
        lang = context['lang']
138
        if current_page.redirect_to_url:
139
            return HttpResponsePermanentRedirect(current_page.redirect_to_url)
140
141
        if current_page.redirect_to:
142
            return HttpResponsePermanentRedirect(
143
                current_page.redirect_to.get_url_path(lang))
144
145
    def get_navigation(self, request, path, lang):
146
        """Get the pages that are at the root level."""
147
        return Page.objects.navigation().order_by("tree_id")
148
149
    def choose_language(self, lang, request):
150
        """Deal with the multiple corner case of choosing the language."""
151
152
        # Can be an empty string or None
153
        if not lang:
154
            lang = get_language_from_request(request)
155
156
        # Raise a 404 if the language is not in not in the list
157
        if lang not in [key for (key, value) in settings.PAGE_LANGUAGES]:
158
            raise Http404
159
160
        # We're going to serve CMS pages in language lang;
161
        # make django gettext use that language too
162
        if lang and translation.check_for_language(lang):
163
            translation.activate(lang)
164
165
        return lang
166
167
    def get_template(self, request, context):
168
        """Just there in case you have special business logic."""
169
        return context['current_page'].get_template()
170
171
    def is_user_staff(self, request):
172
        """Return True if the user is staff."""
173
        return request.user.is_authenticated() and request.user.is_staff
174
175
    def extra_context(self, request, context):
176
        """Call the PAGE_EXTRA_CONTEXT function if there is one."""
177
        if settings.PAGE_EXTRA_CONTEXT:
178
            context.update(settings.PAGE_EXTRA_CONTEXT())
179
180
    def delegate(self, request, context, delegation=True):
181
        # if there is a delegation to another view,
182
        # call this view instead.
183
        current_page = context['current_page']
184
        path = context['path']
185
        delegate_path = path.replace(
186
            current_page.get_complete_slug(hideroot=False), "")
187
        # it seems that the urlconf path have to start with a slash
188
        if len(delegate_path) == 0:
189
            delegate_path = "/"
190
        if delegate_path.startswith("//"):
191
            delegate_path = delegate_path[1:]
192
        urlconf = get_urlconf(current_page.delegate_to)
193
        try:
194
            result = resolve(delegate_path, urlconf)
195
        except Resolver404:
196
            raise Http404
197
        if result:
198
            view, args, kwargs = result
199
            kwargs.update(context)
200
            # for now the view is called as is.
201
            return view(request, *args, **kwargs)
202
203
204
# The Details view instance. It's the same object for
205
# everybody so be careful to maintain it thread safe.
206
# ie: NO self.attribute = something
207
details = Details()
208
209
210
class PageSitemap(Sitemap):
211
    """This site map implementation expose the pages
212
    in the default language only."""
213
    changefreq = "weekly"
214
    priority = 0.5
215
216
    def items(self):
217
        return Page.objects.published()
218
219
    def lastmod(self, obj):
220
        return obj.last_modification_date
221
222
223
class PageItemProxy(object):
224
225
    def __init__(self, page, lang):
226
        self.page = page
227
        self.lang = lang
228
229
    def get_absolute_url(self):
230
        return self.page.get_absolute_url(language=self.lang)
231
232
233
class MultiLanguagePageSitemap(Sitemap):
234
    """This site map implementation expose the pages
235
    in all the languages."""
236
    changefreq = "weekly"
237
    priority = 0.5
238
239
    def items(self):
240
        item_list = []
241
        for page in Page.objects.published():
242
            for lang in page.get_languages():
243
                item_list.append(PageItemProxy(page, lang))
244
        return item_list
245
246
    def lastmod(self, obj):
247
        return obj.page.last_modification_date
248