Piki is a minimal wiki
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

views.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. from django.conf import settings
  2. from django.contrib import messages as django_messages
  3. from django.shortcuts import render
  4. from django.http import HttpResponse, HttpResponseRedirect
  5. from django.utils.translation import gettext as _
  6. import logging
  7. from .access import access_control
  8. from . import messages
  9. from . import url_page
  10. from . import get_search_query
  11. import config
  12. from .context import context_adaption
  13. from .forms import EditForm, RenameForm
  14. from .help import help_pages
  15. from .models import PikiPage, page_list
  16. import mycreole
  17. from .search import whoosh_search, load_index, delete_item, add_item, update_item
  18. from themes import Context
  19. logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__)
  20. SUCCESS_PAGE = _("""= Default startpage
  21. **Congratulations!!!**
  22. Seeing this page means, that you installed Piki successfull.
  23. Edit this page to get your own first startpage.
  24. If you need need assistance to edit a page, visit the [[/helpview/main|help pages]].
  25. """)
  26. def root(request):
  27. return HttpResponseRedirect(url_page(config.STARTPAGE))
  28. def page(request, rel_path):
  29. context = Context(request) # needs to be executed first because of time mesurement
  30. #
  31. try:
  32. p = PikiPage.objects.get(rel_path=rel_path)
  33. except PikiPage.DoesNotExist:
  34. p = None
  35. meta = "meta" in request.GET
  36. history = request.GET.get("history")
  37. if history:
  38. history = int(history)
  39. #
  40. title = rel_path.split("/")[-1]
  41. #
  42. acc = access_control(request, rel_path)
  43. if acc.may_read():
  44. if p is None or p.deleted:
  45. if rel_path == config.STARTPAGE:
  46. page_content = mycreole.render_simple(SUCCESS_PAGE)
  47. else:
  48. page_content = ""
  49. if p is not None and p.deleted:
  50. messages.deleted_page(request)
  51. else:
  52. messages.unavailable_msg_page(request, rel_path)
  53. else:
  54. title = p.title
  55. if meta:
  56. page_content = p.render_meta(request, history)
  57. else:
  58. page_content = p.render_to_html(request, history)
  59. if history:
  60. messages.history_version_display(request, rel_path, history)
  61. else:
  62. messages.permission_denied_msg_page(request, rel_path)
  63. page_content = ""
  64. #
  65. context_adaption(
  66. context,
  67. request,
  68. rel_path=rel_path,
  69. title=title,
  70. upload_path=rel_path,
  71. page_content=page_content,
  72. is_available=p is not None and not p.deleted
  73. )
  74. return render(request, 'pages/page.html', context=context)
  75. def edit(request, rel_path):
  76. acc = access_control(request, rel_path)
  77. if acc.may_write():
  78. context = Context(request) # needs to be executed first because of time mesurement
  79. #
  80. try:
  81. p = PikiPage.objects.get(rel_path=rel_path)
  82. is_available = True
  83. except PikiPage.DoesNotExist:
  84. p = PikiPage(rel_path=rel_path)
  85. is_available = False
  86. #
  87. if not request.POST:
  88. history = request.GET.get("history")
  89. if history:
  90. history = int(history)
  91. form = EditForm(instance=p.history.get(history_id=history))
  92. else:
  93. form = EditForm(instance=p)
  94. #
  95. context_adaption(
  96. context,
  97. request,
  98. rel_path=rel_path,
  99. is_available=is_available,
  100. form=form,
  101. # TODO: Add translation
  102. title=_("Edit page %s") % repr(p.title),
  103. upload_path=rel_path,
  104. )
  105. return render(request, 'pages/page_edit.html', context=context)
  106. else:
  107. form = EditForm(request.POST, instance=p)
  108. #
  109. save = request.POST.get("save")
  110. preview = request.POST.get("preview")
  111. #
  112. if save is not None:
  113. if form.is_valid():
  114. form.instance.prepare_save(request)
  115. page = form.save()
  116. if page.save_needed:
  117. messages.edit_success(request)
  118. # update search index
  119. update_item(page)
  120. else:
  121. messages.no_change(request)
  122. else:
  123. messages.internal_error(request)
  124. return HttpResponseRedirect(url_page(rel_path))
  125. elif preview is not None:
  126. context_adaption(
  127. context,
  128. request,
  129. rel_path=rel_path,
  130. is_available=is_available,
  131. form=form,
  132. # TODO: Add translation
  133. title=_("Edit page %s") % repr(p.title),
  134. upload_path=rel_path,
  135. page_content=p.render_text(request, form.data.get("page_txt"))
  136. )
  137. return render(request, 'pages/page_edit.html', context=context)
  138. else:
  139. return HttpResponseRedirect(url_page(rel_path))
  140. else:
  141. messages.permission_denied_msg_page(request, rel_path)
  142. return HttpResponseRedirect(url_page(rel_path))
  143. def delete(request, rel_path):
  144. acc = access_control(request, rel_path)
  145. if acc.may_write():
  146. context = Context(request) # needs to be executed first because of time mesurement
  147. #
  148. try:
  149. p = PikiPage.objects.get(rel_path=rel_path)
  150. is_available = True
  151. except PikiPage.DoesNotExist:
  152. p = PikiPage(rel_path=rel_path)
  153. is_available = False
  154. #
  155. if not request.POST:
  156. #
  157. # form = DeleteForm(page_data=p.raw_page_src, page_tags=p.tags)
  158. #
  159. context_adaption(
  160. context,
  161. request,
  162. rel_path=rel_path,
  163. is_available=is_available,
  164. # TODO: Add translation
  165. title=_("Delete page %s") % repr(p.title),
  166. upload_path=rel_path,
  167. page_content=p.render_to_html(request),
  168. )
  169. else:
  170. delete = request.POST.get("delete")
  171. #
  172. if delete:
  173. p.deleted = True
  174. p.save()
  175. # delete page from search index
  176. ix = load_index()
  177. delete_item(ix, p)
  178. # add delete message
  179. messages.page_deleted(request, p.title)
  180. return HttpResponseRedirect("/")
  181. else:
  182. messages.operation_canceled(request)
  183. return HttpResponseRedirect(url_page(rel_path))
  184. return render(request, 'pages/page_delete.html', context=context)
  185. else:
  186. messages.permission_denied_msg_page(request, rel_path)
  187. return HttpResponseRedirect(url_page(rel_path))
  188. def rename(request, rel_path):
  189. acc = access_control(request, rel_path)
  190. if acc.may_write():
  191. context = Context(request) # needs to be executed first because of time mesurement
  192. #
  193. try:
  194. p = PikiPage.objects.get(rel_path=rel_path)
  195. is_available = True
  196. except PikiPage.DoesNotExist:
  197. p = PikiPage(rel_path=rel_path)
  198. is_available = False
  199. #
  200. if not request.POST:
  201. form = RenameForm(page_name=p.rel_path)
  202. #
  203. context_adaption(
  204. context,
  205. request,
  206. rel_path=rel_path,
  207. is_available=is_available,
  208. form=form,
  209. # TODO: Add translation
  210. title=_("Delete page %s") % repr(p.title),
  211. upload_path=rel_path,
  212. page_content=p.render_to_html(request),
  213. )
  214. else:
  215. rename = request.POST.get("rename")
  216. page_name = request.POST.get("page_name")
  217. if rename:
  218. if page_name == p.rel_path:
  219. messages.no_change(request)
  220. else:
  221. # delete page from search index
  222. ix = load_index()
  223. delete_item(ix, p)
  224. # rename the storage folder
  225. p.rel_path = page_name
  226. p.save()
  227. # add the renamed page to the search index
  228. add_item(ix, p)
  229. # add rename message
  230. messages.page_renamed(request)
  231. else:
  232. messages.operation_canceled(request)
  233. return HttpResponseRedirect(url_page(p.rel_path))
  234. return render(request, 'pages/page_rename.html', context=context)
  235. else:
  236. messages.permission_denied_msg_page(request, rel_path)
  237. return HttpResponseRedirect(url_page(rel_path))
  238. def search(request):
  239. context = Context(request) # needs to be executed first because of time mesurement
  240. #
  241. search_txt = get_search_query(request)
  242. sr = whoosh_search(search_txt)
  243. if sr is None:
  244. django_messages.error(request, _('Invalid search pattern: %s') % repr(search_txt))
  245. sr = []
  246. pl = page_list([PikiPage.objects.get(rel_path=rel_path) for rel_path in set(sr)])
  247. #
  248. context_adaption(
  249. context,
  250. request,
  251. title=_("Searchresults"),
  252. page_content=mycreole.render_simple(pl.creole_list())
  253. )
  254. return render(request, 'pages/page.html', context=context)
  255. def helpview(request, page='main'):
  256. context = Context(request) # needs to be executed first because of time mesurement
  257. page_content = help_pages[page]
  258. context_adaption(
  259. context, # the base context
  260. request, # the request object to be used in context_adaption
  261. current_help_page=page, # the current help_page to identify which taskbar entry has to be highlighted
  262. page_content=page_content, # the help content itself (template)
  263. title=_('Help') # the title for the page (template)
  264. )
  265. return render(request, 'pages/page.html', context=context)