Source code for evennia.web.website.views.help

"""
Views to manipulate help entries.

"""

from django.utils.text import slugify
from django.views.generic import ListView
from django.http import HttpResponseBadRequest
from django.db.models.functions import Lower
from evennia.help.models import HelpEntry
from .mixins import TypeclassMixin, EvenniaDetailView


[docs]class HelpMixin(TypeclassMixin): """ This is a "mixin", a modifier of sorts. Any view class with this in its inheritance list will be modified to work with HelpEntry objects instead of generic Objects or otherwise. """ # -- Django constructs -- model = HelpEntry # -- Evennia constructs -- page_title = "Help"
[docs] def get_queryset(self): """ Django hook; here we want to return a list of only those HelpEntries and other documentation that the current user is allowed to see. Returns: queryset (QuerySet): List of Help entries available to the user. """ account = self.request.user # Get list of all HelpEntries entries = self.typeclass.objects.all().iterator() # Now figure out which ones the current user is allowed to see bucket = [entry.id for entry in entries if entry.access(account, "view")] # Re-query and set a sorted list filtered = ( self.typeclass.objects.filter(id__in=bucket) .order_by(Lower("db_key")) .order_by(Lower("db_help_category")) ) return filtered
[docs]class HelpListView(HelpMixin, ListView): """ Returns a list of help entries that can be viewed by a user, authenticated or not. """ # -- Django constructs -- paginate_by = 500 template_name = "website/help_list.html" # -- Evennia constructs -- page_title = "Help Index"
[docs]class HelpDetailView(HelpMixin, EvenniaDetailView): """ Returns the detail page for a given help entry. """ # -- Django constructs -- template_name = "website/help_detail.html"
[docs] def get_context_data(self, **kwargs): """ Adds navigational data to the template to let browsers go to the next or previous entry in the help list. Returns: context (dict): Django context object """ context = super().get_context_data(**kwargs) # Get the object in question obj = self.get_object() # Get queryset and filter out non-related categories queryset = ( self.get_queryset() .filter(db_help_category=obj.db_help_category) .order_by(Lower("db_key")) ) context["topic_list"] = queryset # Find the index position of the given obj in the queryset objs = list(queryset) for i, x in enumerate(objs): if obj is x: break # Find the previous and next topics, if either exist try: assert i + 1 <= len(objs) and objs[i + 1] is not obj context["topic_next"] = objs[i + 1] except: context["topic_next"] = None try: assert i - 1 >= 0 and objs[i - 1] is not obj context["topic_previous"] = objs[i - 1] except: context["topic_previous"] = None # Format the help entry using HTML instead of newlines text = obj.db_entrytext text = text.replace("\r\n\r\n", "\n\n") text = text.replace("\r\n", "\n") text = text.replace("\n", "<br />") context["entry_text"] = text return context
[docs] def get_object(self, queryset=None): """ Override of Django hook that retrieves an object by category and topic instead of pk and slug. Returns: entry (HelpEntry): HelpEntry requested in the URL. """ # Get the queryset for the help entries the user can access if not queryset: queryset = self.get_queryset() # Find the object in the queryset category = slugify(self.kwargs.get("category", "")) topic = slugify(self.kwargs.get("topic", "")) obj = next( ( x for x in queryset if slugify(x.db_help_category) == category and slugify(x.db_key) == topic ), None, ) # Check if this object was requested in a valid manner if not obj: return HttpResponseBadRequest( "No %(verbose_name)s found matching the query" % {"verbose_name": queryset.model._meta.verbose_name} ) return obj