werkzeug
203 строки · 6.4 Кб
1"""The per page actions. The actions are defined in the URL with the
2``action`` parameter and directly dispatched to the functions in this
3module. In the module the actions are prefixed with '`on_`', so be
4careful not to name any other objects in the module with the same prefix
5unless you want to act them as actions.
6"""
7from difflib import unified_diff
8
9from werkzeug.utils import redirect
10
11from .database import Page
12from .database import Revision
13from .database import RevisionedPage
14from .database import session
15from .utils import format_datetime
16from .utils import generate_template
17from .utils import href
18from .utils import Response
19
20
21def on_show(request, page_name):
22"""Displays the page the user requests."""
23revision_id = request.args.get("rev", type=int)
24query = RevisionedPage.query.filter_by(name=page_name)
25if revision_id:
26query = query.filter_by(revision_id=revision_id)
27revision_requested = True
28else:
29query = query.order_by(RevisionedPage.revision_id.desc())
30revision_requested = False
31page = query.first()
32if page is None:
33return page_missing(request, page_name, revision_requested)
34return Response(generate_template("action_show.html", page=page))
35
36
37def on_edit(request, page_name):
38"""Edit the current revision of a page."""
39change_note = error = ""
40revision = (
41Revision.query.filter(
42(Page.name == page_name) & (Page.page_id == Revision.page_id)
43)
44.order_by(Revision.revision_id.desc())
45.first()
46)
47if revision is None:
48page = None
49else:
50page = revision.page
51
52if request.method == "POST":
53text = request.form.get("text")
54if request.form.get("cancel") or revision and revision.text == text:
55return redirect(href(page.name))
56elif not text:
57error = "You cannot save empty revisions."
58else:
59change_note = request.form.get("change_note", "")
60if page is None:
61page = Page(page_name)
62session.add(page)
63session.add(Revision(page, text, change_note))
64session.commit()
65return redirect(href(page.name))
66
67return Response(
68generate_template(
69"action_edit.html",
70revision=revision,
71page=page,
72new=page is None,
73page_name=page_name,
74change_note=change_note,
75error=error,
76)
77)
78
79
80def on_log(request, page_name):
81"""Show the list of recent changes."""
82page = Page.query.filter_by(name=page_name).first()
83if page is None:
84return page_missing(request, page_name, False)
85return Response(generate_template("action_log.html", page=page))
86
87
88def on_diff(request, page_name):
89"""Show the diff between two revisions."""
90old = request.args.get("old", type=int)
91new = request.args.get("new", type=int)
92error = ""
93diff = page = old_rev = new_rev = None
94
95if not (old and new):
96error = "No revisions specified."
97else:
98revisions = {
99x.revision_id: x
100for x in Revision.query.filter(
101(Revision.revision_id.in_((old, new)))
102& (Revision.page_id == Page.page_id)
103& (Page.name == page_name)
104)
105}
106if len(revisions) != 2:
107error = "At least one of the revisions requested does not exist."
108else:
109new_rev = revisions[new]
110old_rev = revisions[old]
111page = old_rev.page
112diff = unified_diff(
113f"{old_rev.text}\n".splitlines(True),
114f"{new_rev.text}\n".splitlines(True),
115page.name,
116page.name,
117format_datetime(old_rev.timestamp),
118format_datetime(new_rev.timestamp),
1193,
120)
121
122return Response(
123generate_template(
124"action_diff.html",
125error=error,
126old_revision=old_rev,
127new_revision=new_rev,
128page=page,
129diff=diff,
130)
131)
132
133
134def on_revert(request, page_name):
135"""Revert an old revision."""
136rev_id = request.args.get("rev", type=int)
137
138old_revision = page = None
139error = "No such revision"
140
141if request.method == "POST" and request.form.get("cancel"):
142return redirect(href(page_name))
143
144if rev_id:
145old_revision = Revision.query.filter(
146(Revision.revision_id == rev_id)
147& (Revision.page_id == Page.page_id)
148& (Page.name == page_name)
149).first()
150if old_revision:
151new_revision = (
152Revision.query.filter(
153(Revision.page_id == Page.page_id) & (Page.name == page_name)
154)
155.order_by(Revision.revision_id.desc())
156.first()
157)
158if old_revision == new_revision:
159error = "You tried to revert the current active revision."
160elif old_revision.text == new_revision.text:
161error = (
162"There are no changes between the current "
163"revision and the revision you want to "
164"restore."
165)
166else:
167error = ""
168page = old_revision.page
169if request.method == "POST":
170change_note = request.form.get("change_note", "")
171
172if change_note:
173change_note = f"revert: {change_note}"
174else:
175change_note = "revert"
176
177session.add(Revision(page, old_revision.text, change_note))
178session.commit()
179return redirect(href(page_name))
180
181return Response(
182generate_template(
183"action_revert.html", error=error, old_revision=old_revision, page=page
184)
185)
186
187
188def page_missing(request, page_name, revision_requested, protected=False):
189"""Displayed if page or revision does not exist."""
190return Response(
191generate_template(
192"page_missing.html",
193page_name=page_name,
194revision_requested=revision_requested,
195protected=protected,
196),
197status=404,
198)
199
200
201def missing_action(request, action):
202"""Displayed if a user tried to access a action that does not exist."""
203return Response(generate_template("missing_action.html", action=action), status=404)
204