2025.09.17-19:07:57
This commit is contained in:
2
tinywiki/views/__init__.py
Normal file
2
tinywiki/views/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .home import *
|
||||
from .page import *
|
||||
43
tinywiki/views/base.py
Normal file
43
tinywiki/views/base.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from .. import settings
|
||||
from django.views import View as DjangoView
|
||||
from django.views.generic import FormView as DjangoFormView
|
||||
from typing import Any
|
||||
|
||||
class Base:
|
||||
base_template_name = settings.TINYWIKI_BASE_TEMPLATE
|
||||
|
||||
@classmethod
|
||||
def get_base_template_name(cls)->str:
|
||||
return cls.base_template_name
|
||||
|
||||
@classmethod
|
||||
def get_template_name(cls)->str:
|
||||
return cls.template_name
|
||||
|
||||
def get_tinywiki_context_data(self):
|
||||
create_pages = False
|
||||
if self.request.user.is_authenticated:
|
||||
if self.request.user.is_staff or self.request.user.has_perm('tinywiki.tinywiki-create'):
|
||||
create_pages = True
|
||||
return {
|
||||
'brand_logo': settings.TINYWIKI_BRAND_LOGO,
|
||||
'brand_name': settings.TINYWIKI_BRAND_NAME,
|
||||
'base_template': self.get_base_template_name(),
|
||||
'use_bootstrap': settings.USE_BOOTSTRAP,
|
||||
'user_can_create_wiki_pages':create_pages
|
||||
}
|
||||
|
||||
class View(Base,DjangoView):
|
||||
template_name = "tinywiki"
|
||||
|
||||
def get_context_data(self,**kwargs):
|
||||
context = self.get_tinywiki_context_data()
|
||||
context.update(kwargs)
|
||||
return context
|
||||
|
||||
class FormView(Base,DjangoFormView):
|
||||
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
||||
context = self.get_tinywiki_context_data()
|
||||
context.update(kwargs)
|
||||
return super().get_context_data(**context)
|
||||
|
||||
94
tinywiki/views/home.py
Normal file
94
tinywiki/views/home.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from curses.ascii import isalpha
|
||||
from django.shortcuts import render
|
||||
|
||||
from tinywiki import settings
|
||||
from .base import View
|
||||
from django.http import HttpRequest,HttpResponse
|
||||
from django.db.models.functions import Lower
|
||||
import string
|
||||
from ..models import Page
|
||||
from ..enums import WikiPageStatus
|
||||
from django.utils.translation import ngettext, gettext as _
|
||||
|
||||
# Create your views here.
|
||||
|
||||
class HomeView(View):
|
||||
template_name = "tinywiki/home/home.html"
|
||||
|
||||
def get(self,request):
|
||||
try:
|
||||
page = Page.objects.get(slug='tw-home')
|
||||
except Page.DoesNotExist:
|
||||
page = None
|
||||
|
||||
return render(request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(page=page))
|
||||
|
||||
class TocView(View):
|
||||
template_name = "tinywiki/home/wiki-content.html"
|
||||
bs_template_name = "tinywiki/home/bs-wiki-content.html"
|
||||
|
||||
@classmethod
|
||||
def get_template_name(cls):
|
||||
if settings.USE_BOOTSTRAP:
|
||||
return cls.bs_template_name
|
||||
return cls.template_name
|
||||
|
||||
def get(self,request):
|
||||
def mkdict(page:Page):
|
||||
return {'slug':page.slug,'title':page.title, 'is_system':page.slug.startswith('tw-')}
|
||||
|
||||
user = self.request.user
|
||||
if (user.is_staff or user.has_perm('page.read_all')):
|
||||
pages = Page.objects.all()
|
||||
else:
|
||||
pages = Page.objects.filter(status_data=WikiPageStatus.PUBLISHED.value)
|
||||
|
||||
toc_mapping = {}
|
||||
|
||||
|
||||
for page in pages:
|
||||
first_char = page.title.lstrip()[0].upper()
|
||||
if first_char.isdigit():
|
||||
if '0-9' not in toc_mapping:
|
||||
toc_mapping['0-9'] = [mkdict(page)]
|
||||
else:
|
||||
toc_mapping['0-9'].append(mkdict(page))
|
||||
elif first_char in string.punctuation:
|
||||
if '#' not in toc_mapping:
|
||||
toc_mapping['#'] = [mkdict(page)]
|
||||
else:
|
||||
toc_mapping['#'].append(mkdict(page))
|
||||
else:
|
||||
if first_char not in toc_mapping:
|
||||
toc_mapping[first_char] = [mkdict(page)]
|
||||
else:
|
||||
toc_mapping[first_char].append(mkdict(page))
|
||||
|
||||
toc = []
|
||||
for key in sorted(toc_mapping.keys()):
|
||||
toc_entries = toc_mapping[key]
|
||||
count = len(toc_mapping[key])
|
||||
split = (count + 1) // 2
|
||||
pages_0 = toc_entries[:split]
|
||||
if split >= count:
|
||||
pages_1 = []
|
||||
else:
|
||||
pages_1 = toc_entries[split:]
|
||||
|
||||
|
||||
if (key.startswith('0') or key == '#'):
|
||||
toc_section = key
|
||||
else:
|
||||
toc_section = f"{key}..."
|
||||
|
||||
toc_section = ngettext("{toc_section} ({n} page)","{toc_section} ({n} pages)", count).format(
|
||||
toc_section=toc_section,
|
||||
n=count,
|
||||
)
|
||||
toc.append((toc_section,pages_0,pages_1))
|
||||
|
||||
return render(request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(toc=toc,subtitle=_("Table of Contents")))
|
||||
261
tinywiki/views/page.py
Normal file
261
tinywiki/views/page.py
Normal file
@@ -0,0 +1,261 @@
|
||||
from django.shortcuts import render,get_object_or_404,redirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.http import HttpRequest,HttpResponse
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin,UserPassesTestMixin
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from .. import settings
|
||||
|
||||
from ..models import Page
|
||||
from .base import View,FormView
|
||||
from ..forms import PageForm,PageAdminForm
|
||||
|
||||
class PageView(View):
|
||||
template_name = "tinywiki/page/view.html"
|
||||
bs_template_name = "tinywiki/page/bs-view.html"
|
||||
|
||||
@classmethod
|
||||
def get_template_name(cls) -> str:
|
||||
if settings.USE_BOOTSTRAP:
|
||||
return cls.bs_template_name
|
||||
return cls.template_name
|
||||
|
||||
def get_context_data(self,page,**kwargs):
|
||||
can_edit_page = False
|
||||
can_delete_page = False
|
||||
user = self.request.user
|
||||
if (user.is_staff):
|
||||
can_edit_page = True
|
||||
can_delete_page = True
|
||||
elif page.slug.startswith('tw-'):
|
||||
if user.has_perm('page.tinywiki-edit-system'):
|
||||
can_edit_page = True
|
||||
if user.has_perm('page.tinywiki-delete-system'):
|
||||
can_delete_page = True
|
||||
else:
|
||||
if (user.has_perm('page.tinywiki-edit-all')
|
||||
or (user.pk == page.author.pk and user.has_perm('page.tinywiki-edit'))):
|
||||
can_edit_page = True
|
||||
if (user.has_perm('page.tinywiki-delete-all')
|
||||
or (user.pk == page.author.pk and user.has_perm('page.tinywiki-delete'))):
|
||||
can_delete_page = True
|
||||
|
||||
kwargs.update({'page':page,
|
||||
'user_can_edit_wiki_page':can_edit_page,
|
||||
'user_can_delete_wiki_page':can_delete_page,
|
||||
'subtitle':page.title})
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
def get(self,request:HttpRequest,slug:str)->HttpResponse:
|
||||
page = get_object_or_404(Page,slug=slug)
|
||||
return render(request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(page=page))
|
||||
|
||||
class PageCreateView(LoginRequiredMixin,UserPassesTestMixin,FormView):
|
||||
template_name = "tinywiki/page/create.html"
|
||||
form_class = PageForm
|
||||
|
||||
def test_func(self) -> bool:
|
||||
if self.request.user.is_authenticated:
|
||||
if self.request.user.is_staff:
|
||||
return True
|
||||
return self.request.user.has_perm('tinywiki.tinywiki-create')
|
||||
return False
|
||||
|
||||
def get_context_data(self,**kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['create']=True
|
||||
context.setdefault("title_extra","")
|
||||
context.setdefault("slug_extra","")
|
||||
context.setdefault("content_type_extra","")
|
||||
context.setdefault("status_extra","")
|
||||
context.setdefault("content_extra","")
|
||||
return context
|
||||
|
||||
def form_invalid(self, form):
|
||||
if 'slug' in form.errors:
|
||||
slug_extra = "is-invalid"
|
||||
else:
|
||||
slug_extra = "is-valid"
|
||||
|
||||
if 'title' in form.errors:
|
||||
title_extra = 'is-invalid'
|
||||
else:
|
||||
title_extra = 'is-valid'
|
||||
|
||||
if 'status_data' in form.errors:
|
||||
status_extra = 'is-invalid'
|
||||
else:
|
||||
status_extra = 'is-valid'
|
||||
|
||||
if 'content_type_data' in form.errors:
|
||||
content_type_extra = 'is-invalid'
|
||||
else:
|
||||
content_type_extra = 'is-valid'
|
||||
|
||||
if 'content' in form.errors:
|
||||
content_extra = 'is-invalid'
|
||||
else:
|
||||
content_extra = 'is-valid'
|
||||
|
||||
return render(self.request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(
|
||||
slug_extra=slug_extra,
|
||||
title_extra=title_extra,
|
||||
status_extra=status_extra,
|
||||
content_type_extra=content_type_extra,
|
||||
content_extra=content_extra,
|
||||
))
|
||||
|
||||
def form_valid(self,form):
|
||||
user = self.request.user
|
||||
instance = form.save(commit=False)
|
||||
if (instance.slug.startswith('tw-')
|
||||
and not user.is_staff and
|
||||
not user.has_perm('page.tinywiki-create-system')):
|
||||
return render(self.request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(
|
||||
slug_extra="is-invalid",
|
||||
title_extra="is-valid",
|
||||
status_extra="is-valid",
|
||||
content_type_extra="is-valid",
|
||||
content_extra="is-valid",
|
||||
))
|
||||
|
||||
instance.author = user
|
||||
instance.created_by = user
|
||||
instance.last_edited_by = user
|
||||
try:
|
||||
form.save(commit=True)
|
||||
if self.request.GET.get('save',"0") == "1":
|
||||
return redirect(reverse("tinywiki:page-edit",kwargs={"slug":instance.slug}))
|
||||
return redirect(reverse("tinywiki:page",kwargs={'slug':instance.slug}))
|
||||
except:
|
||||
return render(self.request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(
|
||||
slug_extra="is-invalid",
|
||||
title_extra="is-valid",
|
||||
status_extra="is-valid",
|
||||
content_type_extra="is-valid",
|
||||
content_extra="is-valid",
|
||||
))
|
||||
|
||||
|
||||
class PageEditView(LoginRequiredMixin,UserPassesTestMixin,FormView):
|
||||
template_name = "tinywiki/page/edit.html"
|
||||
form_class = PageForm
|
||||
|
||||
def test_func(self) -> bool:
|
||||
if self.request.user.is_authenticated:
|
||||
if self.request.user.is_staff:
|
||||
return True
|
||||
return False
|
||||
def get_context_data(self,**kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['create']=False
|
||||
context.setdefault("title_extra","")
|
||||
context.setdefault("slug_extra","")
|
||||
context.setdefault("content_type_extra","")
|
||||
context.setdefault("status_extra","")
|
||||
context.setdefault("content_extra","")
|
||||
return context
|
||||
|
||||
def form_invalid(self, form):
|
||||
if 'slug' in form.errors:
|
||||
slug_extra = "is-invalid"
|
||||
else:
|
||||
slug_extra = "is-valid"
|
||||
|
||||
if 'title' in form.errors:
|
||||
title_extra = 'is-invalid'
|
||||
else:
|
||||
title_extra = 'is-valid'
|
||||
|
||||
if 'status_data' in form.errors:
|
||||
status_extra = 'is-invalid'
|
||||
else:
|
||||
status_extra = 'is-valid'
|
||||
|
||||
if 'content_type_data' in form.errors:
|
||||
content_type_extra = 'is-invalid'
|
||||
else:
|
||||
content_type_extra = 'is-valid'
|
||||
|
||||
if 'content' in form.errors:
|
||||
content_extra = 'is-invalid'
|
||||
else:
|
||||
content_extra = 'is-valid'
|
||||
|
||||
return render(self.request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(
|
||||
slug_extra=slug_extra,
|
||||
title_extra=title_extra,
|
||||
status_extra=status_extra,
|
||||
content_type_extra=content_type_extra,
|
||||
content_extra=content_extra,
|
||||
))
|
||||
|
||||
def get(self,request,slug:str):
|
||||
instance = get_object_or_404(Page,slug=slug)
|
||||
user = request.user
|
||||
if (instance.slug.startswith('tw-')
|
||||
and not user.is_staff
|
||||
and not user.has_perm('page.tinywiki-edit-system')):
|
||||
raise PermissionDenied(_("Only staff users and wiki-admins are allowed to edit TinyWiki system pages!"))
|
||||
|
||||
if user.pk != instance.author.pk:
|
||||
if not user.is_staff and not user.has_perm("page.tinywiki-edit-all"):
|
||||
raise PermissionDenied()
|
||||
else:
|
||||
if not user.has_perm('page.tinywiki-edit-all') or not user.has_perm('page.tinywiki-edit'):
|
||||
raise PermissionDenied()
|
||||
|
||||
self.instance = instance
|
||||
return super().get(request)
|
||||
|
||||
def post(self,request,slug:str):
|
||||
instance = get_object_or_404(Page,slug=slug)
|
||||
user = request.user
|
||||
if (instance.slug.startswith('tw-') and not user.is_staff):
|
||||
raise PermissionDenied(_("Only staff users are allowed to edit TinyWiki system pages!"))
|
||||
|
||||
if user.pk != instance.author.pk:
|
||||
if not user.is_staff and not user.has_perm("page.tinywiki-edit-all"):
|
||||
raise PermissionDenied()
|
||||
else:
|
||||
if not user.has_perm('page.tinywiki-edit-all') or not user.has_perm('page.tinywiki-edit'):
|
||||
raise PermissionDenied()
|
||||
|
||||
self.instance = instance
|
||||
|
||||
return super().post(request)
|
||||
|
||||
def get_form(self):
|
||||
return self.get_form_class()(instance=self.instance,**self.get_form_kwargs())
|
||||
|
||||
def form_valid(self,form):
|
||||
user = self.request.user
|
||||
instance = form.save(commit=False)
|
||||
instance.created_by = user
|
||||
instance.last_edited_by = user
|
||||
try:
|
||||
form.save(commit=True)
|
||||
if self.request.GET.get('save',"0") == "1":
|
||||
return redirect(reverse("tinywiki:page-edit",kwargs={"slug":instance.slug}))
|
||||
return redirect(reverse("tinywiki:page",kwargs={'slug':instance.slug}))
|
||||
except:
|
||||
return render(self.request,
|
||||
self.get_template_name(),
|
||||
self.get_context_data(slug_invalid=True))
|
||||
|
||||
class PageDeleteView(View):
|
||||
template_name = "tinywiki/page/delete"
|
||||
def get(self,request,slug):
|
||||
return render()
|
||||
Reference in New Issue
Block a user