Completed
Push — master ( 529ce0...bc8c97 )
by Batiste
01:16
created

PageAdmin.get_fieldsets()   D

Complexity

Conditions 8

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

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