PageAdmin.has_delete_permission()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
1
# -*- coding: utf-8 -*-
2
"""Page Admin module."""
3
from pages import settings
4
from pages.models import Page, Content, PageAlias, Media
5
from pages.phttp import get_language_from_request, get_template_from_request
6
from pages.utils import get_placeholders
7
from pages.templatetags.pages_tags import PlaceholderNode
8
from pages.admin.forms import make_form
9
from pages.admin import views
10
11
from os.path import join
12
from collections import defaultdict
13
from django.contrib import admin
14
from django.utils.translation import ugettext_lazy as _
15
from django.utils.encoding import force_text
16
from django.conf import settings as global_settings
17
from django.http import HttpResponseRedirect, Http404
18
from django.contrib.admin.sites import AlreadyRegistered
19
if global_settings.USE_I18N:
20
    from django.views.i18n import javascript_catalog
21
else:
22
    from django.views.i18n import null_javascript_catalog as javascript_catalog
23
24
25
extra_actions_registery = []
26
def add_page_action(action):
27
    if action not in extra_actions_registery:
28
        extra_actions_registery.append(action)
29
30
31
class PageAdmin(admin.ModelAdmin):
32
    """Page Admin class."""
33
34
    actions = extra_actions_registery
35
36
    # these mandatory fields are not versioned
37
    mandatory_placeholders = ('title', 'slug')
38
    general_fields = [
39
        'title', 'slug', 'status', 'target',
40
        'position', 'freeze_date', 'template', 'language',
41
        'redirect_to', 'redirect_to_url']
42
43
    if settings.PAGE_USE_SITE_ID and not settings.PAGE_HIDE_SITES:
44
        general_fields.append('sites')
45
    insert_point = general_fields.index('status') + 1
46
47
    # Strange django behavior. If not provided, django will try to find
48
    # 'page' foreign key in all registered models
49
    inlines = []
50
51
    if settings.PAGE_TAGGING:
52
        general_fields.insert(insert_point, 'tags')
53
54
    # Add support for future dating and expiration based on settings.
55
    if settings.PAGE_SHOW_END_DATE:
56
        general_fields.insert(insert_point, 'publication_end_date')
57
    if settings.PAGE_SHOW_START_DATE:
58
        general_fields.insert(insert_point, 'publication_date')
59
60
    from pages.urlconf_registry import registry
61
    if(len(registry)):
62
        general_fields.append('delegate_to')
63
        insert_point = general_fields.index('status') + 1
64
65
    page_templates = settings.get_page_templates()
66
67
    fieldsets = (
68
        [_('General'), {
69
            'fields': general_fields,
70
            'classes': ('module-general',),
71
        }],
72
    )
73
74
    class Media:
75
        css = {
76
            'all': [join(settings.PAGES_STATIC_URL, path) for path in (
77
                'css/rte.css',
78
                'css/pages.css'
79
            )]
80
        }
81
        js = [join(settings.PAGES_STATIC_URL, path) for path in (
82
            'javascript/jquery.js',
83
            'javascript/jquery.rte.js',
84
            'javascript/pages.js',
85
            'javascript/pages_list.js',
86
            'javascript/pages_form.js',
87
            'javascript/jquery.query-2.1.7.js',
88
            'javascript/iframeResizer.min.js',
89
        )]
90
91
    def get_urls(self):
92
        urls = super(PageAdmin, self).get_urls()
93
        from django.conf.urls import url
94
95
        pages_urls = [
96
            url(r'^$', self.list_pages, name='page-changelist'),
97
            url(r'^(?P<page_id>[0-9]+)/traduction/(?P<language_id>[-\w]+)/$',
98
                views.traduction, name='page-traduction'),
99
            url(r'^(?P<page_id>[0-9]+)/get-content/(?P<content_id>[0-9]+)/$',
100
                views.get_content, name='page-get-content'),
101
            url(r'^(?P<page_id>[0-9]+)/modify-content/(?P<content_type>[-\w]+)/(?P<language_id>[-\w]+)/$',
102
                views.modify_content, name='page-modify-content'),
103
            url(r'^(?P<page_id>[0-9]+)/modify-placeholder/$',
104
                views.modify_placeholder, name='page-modify-placeholder'),
105
            url(r'^(?P<page_id>[0-9]+)/get-last-content/$',
106
                views.get_last_content, name='page-get-last-content'),
107
            url(r'^(?P<page_id>[0-9]+)/delete-content/(?P<language_id>[-\w]+)/$',
108
                views.delete_content, name='page-delete-content'),
109
            url(r'^(?P<page_id>[0-9]+)/sub-menu/$',
110
                views.sub_menu, name='page-sub-menu'),
111
            url(r'^(?P<page_id>[0-9]+)/move-page/$',
112
                views.move_page, name='page-move-page'),
113
            url(r'^(?P<page_id>[0-9]+)/change-status/$',
114
                views.change_status, name='page-change-status'),
115
            url(r'^(?P<media_id>[0-9]+)/media-url/$',
116
                views.get_media_url, name='get-media-url'),
117
        ]
118
119
        return pages_urls + urls
120
121
122
    def i18n_javascript(self, request):
123
        """Displays the i18n JavaScript that the Django admin
124
        requires.
125
126
        This takes into account the ``USE_I18N`` setting. If it's set to False, the
127
        generated JavaScript will be leaner and faster.
128
        """
129
        return javascript_catalog(request, packages='pages')
130
131
    def save_model(self, request, page, form, change):
132
        """Move the page in the tree if necessary and save every
133
        placeholder :class:`Content <pages.models.Content>`.
134
        """
135
        language = form.cleaned_data['language']
136
        target = form.data.get('target', None)
137
        position = form.data.get('position', None)
138
        page.save()
139
140
        # if True, we need to move the page
141
        if target and position:
142
            try:
143
                target = self.model.objects.get(pk=target)
144
            except self.model.DoesNotExist:
145
                pass
146
            else:
147
                target.invalidate()
148
                page.move_to(target, position)
149
150
        for name in self.mandatory_placeholders:
151
            data = form.cleaned_data[name]
152
            placeholder = PlaceholderNode(name)
153
            extra_data = placeholder.get_extra_data(form.data)
154
            placeholder.save(page, language, data, change,
155
                extra_data=extra_data)
156
157
        for placeholder in get_placeholders(page.get_template()):
158
            if(placeholder.ctype in form.cleaned_data and placeholder.ctype
159
                    not in self.mandatory_placeholders):
160
                data = form.cleaned_data[placeholder.ctype]
161
                extra_data = placeholder.get_extra_data(form.data)
162
                placeholder.save(page, language, data, change,
163
                    extra_data=extra_data)
164
165
        page.invalidate()
166
167
    def get_fieldsets(self, request, obj=None):
168
        """
169
        Add fieldsets of placeholders to the list of already
170
        existing fieldsets.
171
        """
172
173
        # some ugly business to remove freeze_date
174
        # from the field list
175
        general_module = {
176
            'fields': list(self.general_fields),
177
            'classes': ('module-general',),
178
        }
179
180
        default_fieldsets = list(self.fieldsets)
181
        if not request.user.has_perm('pages.can_freeze'):
182
            general_module['fields'].remove('freeze_date')
183
        if not request.user.has_perm('pages.can_publish'):
184
            general_module['fields'].remove('status')
185
186
        default_fieldsets[0][1] = general_module
187
188
        placeholder_fieldsets = []
189
        section_placeholder_fieldsets = defaultdict(list)
190
        template = get_template_from_request(request, obj)
191
        for placeholder in get_placeholders(template):
192
            if placeholder.ctype not in self.mandatory_placeholders and not placeholder.section:
193
                placeholder_fieldsets.append(placeholder.ctype)
194
            elif placeholder.section:
195
                section_placeholder_fieldsets[placeholder.section].append(placeholder.ctype)
196
197
        additional_fieldsets = []
198
        for title, fieldset in section_placeholder_fieldsets.items():
199
            additional_fieldsets.append((title, {
200
                'fields': fieldset,
201
                'classes': ('module-content collapse grp-collapse grp-closed',),
202
            }))
203
        additional_fieldsets.append((_('Content'), {
204
            'fields': placeholder_fieldsets,
205
            'classes': ('module-content',),
206
        }))
207
        return default_fieldsets + additional_fieldsets
208
209
    def save_form(self, request, form, change):
210
        """Given a ModelForm return an unsaved instance. ``change`` is True if
211
        the object is being changed, and False if it's being added."""
212
        instance = super(PageAdmin, self).save_form(request, form, change)
213
        instance.template = form.cleaned_data['template']
214
        if not change:
215
            instance.author = request.user
216
        return instance
217
218
    def get_form(self, request, obj=None, **kwargs):
219
        """Get a :class:`Page <pages.admin.forms.PageForm>` for the
220
        :class:`Page <pages.models.Page>` and modify its fields depending on
221
        the request."""
222
223
        template = get_template_from_request(request, obj)
224
225
        #model = create_page_model(get_placeholders(template))
226
227
        form = make_form(self.model, get_placeholders(template))
228
229
        # bound the form
230
        language = get_language_from_request(request)
231
        form.base_fields['language'].initial = language
232
        if obj:
233
            initial_slug = obj.slug(language=language, fallback=False)
234
            initial_title = obj.title(language=language, fallback=False)
235
            form.base_fields['slug'].initial = initial_slug
236
            form.base_fields['title'].initial = initial_title
237
238
        template = get_template_from_request(request, obj)
239
        page_templates = settings.get_page_templates()
240
        template_choices = list(page_templates)
241
        # is default template is not in the list add it
242
        if not [tpl for tpl in template_choices if tpl[0] == settings.PAGE_DEFAULT_TEMPLATE]:
243
            template_choices.insert(0, (settings.PAGE_DEFAULT_TEMPLATE,
244
                    _('Default template')))
245
        form.base_fields['template'].choices = template_choices
246
        form.base_fields['template'].initial = force_text(template)
247
248
        for placeholder in get_placeholders(template):
249
            ctype = placeholder.ctype
250
            if obj:
251
                initial = placeholder.get_content(obj, language, lang_fallback=False)
252
            else:
253
                initial = None
254
            form.base_fields[ctype] = placeholder.get_field(obj,
255
                language, initial=initial)
256
257
        return form
258
259
    def change_view(self, request, object_id, form_url='', extra_context=None):
260
        """The ``change`` admin view for the
261
        :class:`Page <pages.models.Page>`."""
262
        language = get_language_from_request(request)
263
        extra_context = {
264
            'language': language,
265
            'page_languages': settings.PAGE_LANGUAGES,
266
        }
267
        try:
268
            int(object_id)
269
        except ValueError:
270
            raise Http404('The "%s" part of the location is invalid.'
271
                % str(object_id))
272
        try:
273
            obj = self.model.objects.get(pk=object_id)
274
        except self.model.DoesNotExist:
275
            # Don't raise Http404 just yet, because we haven't checked
276
            # permissions yet. We don't want an unauthenticated user to be able
277
            # to determine whether a given object exists.
278
            obj = None
279
        else:
280
            template = get_template_from_request(request, obj)
281
            extra_context['placeholders'] = get_placeholders(template)
282
            extra_context['traduction_languages'] = [l for l in
283
                settings.PAGE_LANGUAGES if Content.objects.get_content(obj,
284
                                    l[0], "title") and l[0] != language]
285
        extra_context['page'] = obj
286
287
        response = super(PageAdmin, self).change_view(request, object_id,
288
            form_url=form_url, extra_context=extra_context)
289
        if request.method == 'POST' and isinstance(response, HttpResponseRedirect):
290
            if '_continue' in request.POST or '_saveasnew' in request.POST or '_addanother' in request.POST:
291
                addlanguage = True
292
            else:
293
                addlanguage = False
294
            if addlanguage:
295
                from six.moves import urllib
296
                splitted = list(urllib.parse.urlparse(response.url))
297
                query = urllib.parse.parse_qs(splitted[4])
298
                query['language'] = language
299
                splitted[4] = urllib.parse.urlencode(query)
300
                response = HttpResponseRedirect(urllib.parse.urlunparse(splitted))
301
        return response
302
303
    def add_view(self, request, form_url='', extra_context=None):
304
        """The ``add`` admin view for the :class:`Page <pages.models.Page>`."""
305
        extra_context = {
306
            'language': get_language_from_request(request),
307
            'page_languages': settings.PAGE_LANGUAGES,
308
        }
309
        return super(PageAdmin, self).add_view(request, form_url,
310
                                               extra_context)
311
312
    def has_add_permission(self, request):
313
        """Return ``True`` if the current user has permission to add a new
314
        page."""
315
        return request.user.has_perm('pages.add_page')
316
317
    def has_change_permission(self, request, obj=None):
318
        """Return ``True`` if the current user has permission
319
        to change the page."""
320
        return request.user.has_perm('pages.change_page')
321
322
    def has_delete_permission(self, request, obj=None):
323
        """Return ``True`` if the current user has permission on the page."""
324
        return request.user.has_perm('pages.delete_page')
325
326
    def list_pages(self, request, template_name=None, extra_context=None):
327
        """List root pages"""
328
        if not self.admin_site.has_permission(request):
329
            return self.admin_site.login(request)
330
        language = get_language_from_request(request)
331
332
        query = request.POST.get('q', '').strip()
333
334
        if query:
335
            page_ids = list(set([c.page.pk for c in
336
                Content.objects.filter(body__icontains=query)]))
337
            pages = Page.objects.filter(pk__in=page_ids)
338
        else:
339
            pages = Page.objects.root()
340
        if settings.PAGE_HIDE_SITES:
341
            pages = pages.filter(sites=global_settings.SITE_ID)
342
343
        context = {
344
            'can_publish': request.user.has_perm('pages.can_publish'),
345
            'can_import': settings.PAGE_IMPORT_ENABLED,
346
            'lang': language,  # lang is the key used by show_content
347
            'pages': pages,
348
            'opts': self.model._meta,
349
            'q': query
350
        }
351
352
        context.update(extra_context or {})
353
        change_list = self.changelist_view(request, context)
354
355
        return change_list
356
357
358
try:
359
    admin.site.register(Page, PageAdmin)
360
except AlreadyRegistered:
361
    pass
362
363
class ContentAdmin(admin.ModelAdmin):
364
    list_display = ('__unicode__', 'type', 'language', 'page')
365
    list_filter = ('page',)
366
    search_fields = ('body',)
367
368
369
class AliasAdmin(admin.ModelAdmin):
370
    list_display = ('page', 'url',)
371
    list_editable = ('url',)
372
    raw_id_fields = ['page']
373
374
try:
375
    admin.site.register(PageAlias, AliasAdmin)
376
except AlreadyRegistered:
377
    pass
378
379
380
class MediaAdmin(admin.ModelAdmin):
381
    list_display = ('image', 'title', 'creation_date', 'description', 'extension')
382
    list_display_links = ('image', 'title', )
383
384
try:
385
    admin.site.register(Media, MediaAdmin)
386
except AlreadyRegistered:
387
    pass