Completed
Push — master ( 3a953a...d07ac3 )
by Batiste
01:25
created

PageAdmin

Size/Duplication

Total Lines 313
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 313

13 Methods

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