1 35
from time import time
2

3 35
from django.contrib.contenttypes.models import ContentType
4 35
from django.core.exceptions import PermissionDenied
5 35
from django.http import Http404, JsonResponse
6 35
from django.http.request import QueryDict
7 35
from django.shortcuts import get_object_or_404
8 35
from django.template.response import TemplateResponse
9 35
from django.views.generic import View
10

11 35
from wagtail.core.models import Page
12

13

14 35
def view_draft(request, page_id):
15 21
    page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
16 21
    perms = page.permissions_for_user(request.user)
17 35
    if not (perms.can_publish() or perms.can_edit()):
18 21
        raise PermissionDenied
19

20 21
    try:
21 21
        preview_mode = page.default_preview_mode
22 21
    except IndexError:
23 21
        raise PermissionDenied
24

25 21
    return page.make_preview_request(request, preview_mode)
26

27

28 35
class PreviewOnEdit(View):
29 35
    http_method_names = ('post', 'get')
30 35
    preview_expiration_timeout = 60 * 60 * 24  # seconds
31 35
    session_key_prefix = 'wagtail-preview-'
32

33 35
    def remove_old_preview_data(self):
34 21
        expiration = time() - self.preview_expiration_timeout
35 35
        expired_keys = [
36
            k for k, v in self.request.session.items()
37
            if k.startswith(self.session_key_prefix) and v[1] < expiration]
38
        # Removes the session key gracefully
39 35
        for k in expired_keys:
40 0
            self.request.session.pop(k)
41

42 35
    @property
43 19
    def session_key(self):
44 21
        return self.session_key_prefix + ','.join(self.args)
45

46 35
    def get_page(self):
47 21
        return get_object_or_404(Page,
48
                                 id=self.kwargs["page_id"]).get_latest_revision_as_page()
49

50 35
    def get_form(self, page, query_dict):
51 21
        form_class = page.get_edit_handler().get_form_class()
52 21
        parent_page = page.get_parent().specific
53

54 35
        if self.session_key not in self.request.session:
55
            # Session key not in session, returning null form
56 21
            return form_class(instance=page, parent_page=parent_page)
57

58 21
        return form_class(query_dict, instance=page, parent_page=parent_page)
59

60 35
    def post(self, request, *args, **kwargs):
61
        # TODO: Handle request.FILES.
62 21
        request.session[self.session_key] = request.POST.urlencode(), time()
63 21
        self.remove_old_preview_data()
64 21
        form = self.get_form(self.get_page(), request.POST)
65 21
        return JsonResponse({'is_valid': form.is_valid()})
66

67 35
    def error_response(self, page):
68 21
        return TemplateResponse(
69
            self.request, 'wagtailadmin/pages/preview_error.html',
70
            {'page': page}
71
        )
72

73 35
    def get(self, request, *args, **kwargs):
74 21
        page = self.get_page()
75

76 21
        post_data, timestamp = self.request.session.get(self.session_key,
77
                                                        (None, None))
78 35
        if not isinstance(post_data, str):
79 21
            post_data = ''
80 21
        form = self.get_form(page, QueryDict(post_data))
81

82 35
        if not form.is_valid():
83 21
            return self.error_response(page)
84

85 21
        form.save(commit=False)
86

87 21
        try:
88 21
            preview_mode = request.GET.get('mode', page.default_preview_mode)
89 0
        except IndexError:
90 0
            raise PermissionDenied
91

92 21
        return page.make_preview_request(request, preview_mode)
93

94

95 35
class PreviewOnCreate(PreviewOnEdit):
96 35
    def get_page(self):
97 21
        content_type_app_name = self.kwargs["content_type_app_name"]
98 21
        content_type_model_name = self.kwargs["content_type_model_name"]
99 21
        parent_page_id = self.kwargs["parent_page_id"]
100 21
        try:
101 21
            content_type = ContentType.objects.get_by_natural_key(
102
                content_type_app_name, content_type_model_name)
103 0
        except ContentType.DoesNotExist:
104 0
            raise Http404
105

106 21
        page = content_type.model_class()()
107 21
        parent_page = get_object_or_404(Page, id=parent_page_id).specific
108
        # We need to populate treebeard's path / depth fields in order to
109
        # pass validation. We can't make these 100% consistent with the rest
110
        # of the tree without making actual database changes (such as
111
        # incrementing the parent's numchild field), but by calling treebeard's
112
        # internal _get_path method, we can set a 'realistic' value that will
113
        # hopefully enable tree traversal operations
114
        # to at least partially work.
115 21
        page.depth = parent_page.depth + 1
116
        # Puts the page at the next available path
117
        # for a child of `parent_page`.
118 35
        if parent_page.is_leaf():
119
            # set the path as the first child of parent_page
120 21
            page.path = page._get_path(parent_page.path, page.depth, 1)
121
        else:
122
            # add the new page after the last child of parent_page
123 21
            page.path = parent_page.get_last_child()._inc_path()
124

125 21
        return page
126

127 35
    def get_form(self, page, query_dict):
128 21
        form = super().get_form(page, query_dict)
129 35
        if form.is_valid():
130
            # Ensures our unsaved page has a suitable url.
131 21
            form.instance.set_url_path(form.parent_page)
132

133 21
            form.instance.full_clean()
134 21
        return form

Read our documentation on viewing source code .

Loading