file and command help web support, proof of concept
Not fleshed enough for a prototype. Is a working proof of concept. Adds command help and file help entries to the website.
This commit is contained in:
parent
d7b66eecca
commit
9eb1c0532f
5 changed files with 310 additions and 37 deletions
|
|
@ -9,11 +9,14 @@ import math
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from evennia.locks.lockhandler import LockHandler
|
from evennia.locks.lockhandler import LockHandler
|
||||||
from evennia.utils.utils import is_iter, fill, lazy_property, make_iter
|
from evennia.utils.utils import is_iter, fill, lazy_property, make_iter
|
||||||
from evennia.utils.evtable import EvTable
|
from evennia.utils.evtable import EvTable
|
||||||
from evennia.utils.ansi import ANSIString
|
from evennia.utils.ansi import ANSIString
|
||||||
|
from evennia.utils.logger import log_info
|
||||||
|
|
||||||
|
|
||||||
class InterruptCommand(Exception):
|
class InterruptCommand(Exception):
|
||||||
|
|
@ -514,6 +517,42 @@ Command {self} has no defined `func()` - showing on-command variables:
|
||||||
"""
|
"""
|
||||||
return self.__doc__
|
return self.__doc__
|
||||||
|
|
||||||
|
def web_get_detail_url(self):
|
||||||
|
"""
|
||||||
|
Returns the URI path for a View that allows users to view details for
|
||||||
|
this object.
|
||||||
|
|
||||||
|
ex. Oscar (Character) = '/characters/oscar/1/'
|
||||||
|
|
||||||
|
For this to work, the developer must have defined a named view somewhere
|
||||||
|
in urls.py that follows the format 'modelname-action', so in this case
|
||||||
|
a named view of 'character-detail' would be referenced by this method.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
::
|
||||||
|
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/$',
|
||||||
|
CharDetailView.as_view(), name='character-detail')
|
||||||
|
|
||||||
|
If no View has been created and defined in urls.py, returns an
|
||||||
|
HTML anchor.
|
||||||
|
|
||||||
|
This method is naive and simply returns a path. Securing access to
|
||||||
|
the actual view and limiting who can view this object is the developer's
|
||||||
|
responsibility.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
path (str): URI path to object detail page, if defined.
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return reverse(
|
||||||
|
'help-entry-detail',
|
||||||
|
kwargs={"category": slugify(self.help_category), "topic": slugify(self.key)},
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
log_info(f'Exception: {getattr(e, "message", repr(e))}')
|
||||||
|
return "#"
|
||||||
|
|
||||||
def client_width(self):
|
def client_width(self):
|
||||||
"""
|
"""
|
||||||
Get the client screenwidth for the session using this command.
|
Get the client screenwidth for the session using this command.
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,14 @@ An example of the contents of a module:
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.text import slugify
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import (
|
||||||
variable_from_module, make_iter, all_from_module)
|
variable_from_module, make_iter, all_from_module)
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils.utils import lazy_property
|
from evennia.utils.utils import lazy_property
|
||||||
from evennia.locks.lockhandler import LockHandler
|
from evennia.locks.lockhandler import LockHandler
|
||||||
|
from evennia.utils.logger import log_info
|
||||||
|
|
||||||
_DEFAULT_HELP_CATEGORY = settings.DEFAULT_HELP_CATEGORY
|
_DEFAULT_HELP_CATEGORY = settings.DEFAULT_HELP_CATEGORY
|
||||||
|
|
||||||
|
|
@ -115,6 +118,43 @@ class FileHelpEntry:
|
||||||
def locks(self):
|
def locks(self):
|
||||||
return LockHandler(self)
|
return LockHandler(self)
|
||||||
|
|
||||||
|
def web_get_detail_url(self):
|
||||||
|
"""
|
||||||
|
Returns the URI path for a View that allows users to view details for
|
||||||
|
this object.
|
||||||
|
|
||||||
|
ex. Oscar (Character) = '/characters/oscar/1/'
|
||||||
|
|
||||||
|
For this to work, the developer must have defined a named view somewhere
|
||||||
|
in urls.py that follows the format 'modelname-action', so in this case
|
||||||
|
a named view of 'character-detail' would be referenced by this method.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
::
|
||||||
|
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/$',
|
||||||
|
CharDetailView.as_view(), name='character-detail')
|
||||||
|
|
||||||
|
If no View has been created and defined in urls.py, returns an
|
||||||
|
HTML anchor.
|
||||||
|
|
||||||
|
This method is naive and simply returns a path. Securing access to
|
||||||
|
the actual view and limiting who can view this object is the developer's
|
||||||
|
responsibility.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
path (str): URI path to object detail page, if defined.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# log_info('filehelp web_get_detail_url start')
|
||||||
|
try:
|
||||||
|
return reverse(
|
||||||
|
'help-entry-detail',
|
||||||
|
kwargs={"category": slugify(self.help_category), "topic": slugify(self.key)},
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
log_info(f'Exception: {getattr(e, "message", repr(e))}')
|
||||||
|
return "#"
|
||||||
|
|
||||||
def access(self, accessing_obj, access_type="view", default=True):
|
def access(self, accessing_obj, access_type="view", default=True):
|
||||||
"""
|
"""
|
||||||
Determines if another object has permission to access this help entry.
|
Determines if another object has permission to access this help entry.
|
||||||
|
|
@ -207,3 +247,5 @@ class FileHelpStorageHandler:
|
||||||
|
|
||||||
# singleton to hold the loaded help entries
|
# singleton to hold the loaded help entries
|
||||||
FILE_HELP_ENTRIES = FileHelpStorageHandler()
|
FILE_HELP_ENTRIES = FileHelpStorageHandler()
|
||||||
|
# Used by Django Sites/Admin
|
||||||
|
#get_absolute_url = web_get_detail_url
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from evennia.help.manager import HelpEntryManager
|
||||||
from evennia.typeclasses.models import Tag, TagHandler, AliasHandler
|
from evennia.typeclasses.models import Tag, TagHandler, AliasHandler
|
||||||
from evennia.locks.lockhandler import LockHandler
|
from evennia.locks.lockhandler import LockHandler
|
||||||
from evennia.utils.utils import lazy_property
|
from evennia.utils.utils import lazy_property
|
||||||
|
from evennia.utils.logger import log_info
|
||||||
|
|
||||||
__all__ = ("HelpEntry",)
|
__all__ = ("HelpEntry",)
|
||||||
|
|
||||||
|
|
@ -221,11 +222,14 @@ class HelpEntry(SharedMemoryModel):
|
||||||
path (str): URI path to object detail page, if defined.
|
path (str): URI path to object detail page, if defined.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return reverse(
|
url = reverse(
|
||||||
"%s-detail" % slugify(self._meta.verbose_name),
|
"%s-detail" % slugify(self._meta.verbose_name),
|
||||||
kwargs={"category": slugify(self.db_help_category), "topic": slugify(self.db_key)},
|
kwargs={"category": slugify(self.db_help_category), "topic": slugify(self.db_key)},
|
||||||
)
|
)
|
||||||
|
# log_info(f'HelpEntry web_get_detail_url url: {url}')
|
||||||
|
return url
|
||||||
except Exception:
|
except Exception:
|
||||||
return "#"
|
return "#"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,17 @@ class ChannelDetailTest(EvenniaWebTest):
|
||||||
return {"slug": slugify("demo")}
|
return {"slug": slugify("demo")}
|
||||||
|
|
||||||
|
|
||||||
|
class HelpListTest(EvenniaWebTest):
|
||||||
|
url_name = "help"
|
||||||
|
|
||||||
|
|
||||||
|
class HelpDetailTest(EvenniaWebTest):
|
||||||
|
url_name = "help-entry-detail"
|
||||||
|
|
||||||
|
def get_kwargs(self):
|
||||||
|
return {"category": slugify("general"),
|
||||||
|
"topic": slugify("test-key")}
|
||||||
|
|
||||||
class CharacterCreateView(EvenniaWebTest):
|
class CharacterCreateView(EvenniaWebTest):
|
||||||
url_name = "character-create"
|
url_name = "character-create"
|
||||||
unauthenticated_response = 302
|
unauthenticated_response = 302
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,152 @@
|
||||||
Views to manipulate help entries.
|
Views to manipulate help entries.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from dataclasses import dataclass
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
from django.conf import settings
|
||||||
|
from evennia.utils.utils import inherits_from
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.http import HttpResponseBadRequest
|
from django.http import HttpResponseBadRequest
|
||||||
from django.db.models.functions import Lower
|
from django.db.models.functions import Lower
|
||||||
from evennia.help.models import HelpEntry
|
from evennia.help.models import HelpEntry
|
||||||
|
from evennia.help.filehelp import FILE_HELP_ENTRIES
|
||||||
from .mixins import TypeclassMixin, EvenniaDetailView
|
from .mixins import TypeclassMixin, EvenniaDetailView
|
||||||
|
from django.views.generic import DetailView
|
||||||
|
from evennia.utils.logger import log_info
|
||||||
|
|
||||||
|
DEFAULT_HELP_CATEGORY = settings.DEFAULT_HELP_CATEGORY
|
||||||
|
|
||||||
|
def get_help_category(help_entry):
|
||||||
|
if hasattr(help_entry, 'help_category'):
|
||||||
|
return help_entry.help_category
|
||||||
|
elif hasattr(help_entry, 'category'):
|
||||||
|
return help_entry.category
|
||||||
|
elif hasattr(help_entry, 'db_help_category'):
|
||||||
|
return help_entry.db_help_category
|
||||||
|
else:
|
||||||
|
return 'unsorted'
|
||||||
|
|
||||||
|
def get_help_topic(help_entry):
|
||||||
|
topic = getattr(help_entry, 'key', False)
|
||||||
|
if not topic:
|
||||||
|
getattr(help_entry, 'db_key', False)
|
||||||
|
# log_info(f'get_help_topic returning: {topic}')
|
||||||
|
return topic
|
||||||
|
|
||||||
|
def can_read_topic(cmd_or_topic, caller):
|
||||||
|
"""
|
||||||
|
Helper method. If this return True, the given help topic
|
||||||
|
be viewable in the help listing. Note that even if this returns False,
|
||||||
|
the entry will still be visible in the help index unless `should_list_topic`
|
||||||
|
is also returning False.
|
||||||
|
Args:
|
||||||
|
cmd_or_topic (Command, HelpEntry or FileHelpEntry): The topic/command to test.
|
||||||
|
caller: the caller checking for access.
|
||||||
|
Returns:
|
||||||
|
bool: If command can be viewed or not.
|
||||||
|
Notes:
|
||||||
|
This uses the 'read' lock. If no 'read' lock is defined, the topic is assumed readable
|
||||||
|
by all.
|
||||||
|
"""
|
||||||
|
if inherits_from(cmd_or_topic, "evennia.commands.command.Command"):
|
||||||
|
return cmd_or_topic.auto_help and cmd_or_topic.access(caller, 'read', default=True)
|
||||||
|
else:
|
||||||
|
return cmd_or_topic.access(caller, 'read', default=True)
|
||||||
|
|
||||||
|
def can_list_topic(cmd_or_topic, caller):
|
||||||
|
"""
|
||||||
|
Should the specified command appear in the help table?
|
||||||
|
This method only checks whether a specified command should appear in the table of
|
||||||
|
topics/commands. The command can be used by the caller (see the 'should_show_help' method)
|
||||||
|
and the command will still be available, for instance, if a character type 'help name of the
|
||||||
|
command'. However, if you return False, the specified command will not appear in the table.
|
||||||
|
This is sometimes useful to "hide" commands in the table, but still access them through the
|
||||||
|
help system.
|
||||||
|
Args:
|
||||||
|
cmd_or_topic (Command, HelpEntry or FileHelpEntry): The topic/command to test.
|
||||||
|
caller: the caller checking for access.
|
||||||
|
Returns:
|
||||||
|
bool: If command should be listed or not.
|
||||||
|
Notes:
|
||||||
|
By default, the 'view' lock will be checked, and if no such lock is defined, the 'read'
|
||||||
|
lock will be used. If neither lock is defined, the help entry is assumed to be
|
||||||
|
accessible to all.
|
||||||
|
"""
|
||||||
|
has_view = (
|
||||||
|
"view:" in cmd_or_topic.locks
|
||||||
|
if inherits_from(cmd_or_topic, "evennia.commands.command.Command")
|
||||||
|
else cmd_or_topic.locks.get("view")
|
||||||
|
)
|
||||||
|
|
||||||
|
if has_view:
|
||||||
|
return cmd_or_topic.access(caller, 'view', default=True)
|
||||||
|
else:
|
||||||
|
# no explicit 'view' lock - use the 'read' lock
|
||||||
|
return cmd_or_topic.access(caller, 'read', default=True)
|
||||||
|
|
||||||
|
def collect_topics(caller, mode='list'):
|
||||||
|
"""
|
||||||
|
Collect help topics from all sources (cmd/db/file).
|
||||||
|
Args:
|
||||||
|
caller (Object or Account): The user of the Command.
|
||||||
|
mode (str): One of 'list' or 'query', where the first means we are collecting to view
|
||||||
|
the help index and the second because of wanting to search for a specific help
|
||||||
|
entry/cmd to read. This determines which access should be checked.
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple of three dicts containing the different types of help entries
|
||||||
|
in the order cmd-help, db-help, file-help:
|
||||||
|
`({key: cmd,...}, {key: dbentry,...}, {key: fileentry,...}`
|
||||||
|
"""
|
||||||
|
# start with cmd-help
|
||||||
|
|
||||||
|
# get Character's primary command set.
|
||||||
|
cmdset = caller.cmdset.get()[0]
|
||||||
|
|
||||||
|
# removing doublets in cmdset, caused by cmdhandler
|
||||||
|
# having to allow doublet commands to manage exits etc.
|
||||||
|
cmdset.make_unique(caller)
|
||||||
|
|
||||||
|
# retrieve all available commands and database / file-help topics.
|
||||||
|
# also check the 'cmd:' lock here
|
||||||
|
cmd_help_topics = [cmd for cmd in cmdset if cmd and cmd.access(caller, 'cmd')]
|
||||||
|
# get all file-based help entries, checking perms
|
||||||
|
file_help_topics = {
|
||||||
|
topic.key.lower().strip(): topic
|
||||||
|
for topic in FILE_HELP_ENTRIES.all()
|
||||||
|
}
|
||||||
|
# get db-based help entries, checking perms
|
||||||
|
db_help_topics = {
|
||||||
|
topic.key.lower().strip(): topic
|
||||||
|
for topic in HelpEntry.objects.all()
|
||||||
|
}
|
||||||
|
if mode == 'list':
|
||||||
|
# check the view lock for all help entries/commands and determine key
|
||||||
|
cmd_help_topics = {
|
||||||
|
cmd.auto_help_display_key
|
||||||
|
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
|
||||||
|
for cmd in cmd_help_topics if can_list_topic(cmd, caller)}
|
||||||
|
db_help_topics = {
|
||||||
|
key: entry for key, entry in db_help_topics.items()
|
||||||
|
if can_list_topic(entry, caller)
|
||||||
|
}
|
||||||
|
file_help_topics = {
|
||||||
|
key: entry for key, entry in file_help_topics.items()
|
||||||
|
if can_list_topic(entry, caller)}
|
||||||
|
else:
|
||||||
|
# query
|
||||||
|
cmd_help_topics = {
|
||||||
|
cmd.auto_help_display_key
|
||||||
|
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
|
||||||
|
for cmd in cmd_help_topics if can_read_topic(cmd, caller)}
|
||||||
|
db_help_topics = {
|
||||||
|
key: entry for key, entry in db_help_topics.items()
|
||||||
|
if can_read_topic(entry, caller)
|
||||||
|
}
|
||||||
|
file_help_topics = {
|
||||||
|
key: entry for key, entry in file_help_topics.items()
|
||||||
|
if can_read_topic(entry, caller)}
|
||||||
|
|
||||||
|
return cmd_help_topics, db_help_topics, file_help_topics
|
||||||
|
|
||||||
class HelpMixin(TypeclassMixin):
|
class HelpMixin(TypeclassMixin):
|
||||||
"""
|
"""
|
||||||
|
|
@ -35,22 +173,36 @@ class HelpMixin(TypeclassMixin):
|
||||||
queryset (QuerySet): List of Help entries available to the user.
|
queryset (QuerySet): List of Help entries available to the user.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
log_info('get_queryset')
|
||||||
account = self.request.user
|
account = self.request.user
|
||||||
|
all_entries = []
|
||||||
|
if not str(account) == 'AnonymousUser':
|
||||||
|
# collect all help entries
|
||||||
|
cmd_help_topics, db_help_topics, file_help_topics = \
|
||||||
|
collect_topics(account.db._playable_characters[0], mode='query')
|
||||||
|
# combine and sort all the help entries
|
||||||
|
file_db_help_topics = {**file_help_topics, **db_help_topics}
|
||||||
|
all_topics = {**file_db_help_topics, **cmd_help_topics}
|
||||||
|
all_entries = list(all_topics.values())
|
||||||
|
all_entries.sort(key=get_help_category)
|
||||||
|
# log_info(f'{all_entries}')
|
||||||
|
log_info('get_queryset success')
|
||||||
|
return all_entries
|
||||||
|
|
||||||
# Get list of all HelpEntries
|
def get_entries(self):
|
||||||
entries = self.typeclass.objects.all().iterator()
|
account = self.request.user
|
||||||
|
all_entries = []
|
||||||
# Now figure out which ones the current user is allowed to see
|
if not str(account) == 'AnonymousUser':
|
||||||
bucket = [entry.id for entry in entries if entry.access(account, "view")]
|
# collect all help entries
|
||||||
|
cmd_help_topics, db_help_topics, file_help_topics = \
|
||||||
# Re-query and set a sorted list
|
collect_topics(account.db._playable_characters[0], mode='query')
|
||||||
filtered = (
|
# combine and sort all the help entries
|
||||||
self.typeclass.objects.filter(id__in=bucket)
|
file_db_help_topics = {**file_help_topics, **db_help_topics}
|
||||||
.order_by(Lower("db_key"))
|
all_topics = {**file_db_help_topics, **cmd_help_topics}
|
||||||
.order_by(Lower("db_help_category"))
|
all_entries = list(all_topics.values())
|
||||||
)
|
all_entries.sort(key=get_help_category)
|
||||||
|
# log_info(f'{all_entries}')
|
||||||
return filtered
|
return all_entries
|
||||||
|
|
||||||
|
|
||||||
class HelpListView(HelpMixin, ListView):
|
class HelpListView(HelpMixin, ListView):
|
||||||
|
|
@ -68,7 +220,7 @@ class HelpListView(HelpMixin, ListView):
|
||||||
page_title = "Help Index"
|
page_title = "Help Index"
|
||||||
|
|
||||||
|
|
||||||
class HelpDetailView(HelpMixin, EvenniaDetailView):
|
class HelpDetailView(HelpMixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Returns the detail page for a given help entry.
|
Returns the detail page for a given help entry.
|
||||||
|
|
||||||
|
|
@ -77,6 +229,14 @@ class HelpDetailView(HelpMixin, EvenniaDetailView):
|
||||||
# -- Django constructs --
|
# -- Django constructs --
|
||||||
template_name = "website/help_detail.html"
|
template_name = "website/help_detail.html"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page_title(self):
|
||||||
|
# Makes sure the page has a sensible title.
|
||||||
|
#return "%s Detail" % self.typeclass._meta.verbose_name.title()
|
||||||
|
obj = self.get_object()
|
||||||
|
topic = get_help_topic(obj)
|
||||||
|
return f'{topic} detail'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Adds navigational data to the template to let browsers go to the next
|
Adds navigational data to the template to let browsers go to the next
|
||||||
|
|
@ -86,21 +246,26 @@ class HelpDetailView(HelpMixin, EvenniaDetailView):
|
||||||
context (dict): Django context object
|
context (dict): Django context object
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
log_info('get_context_data')
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
# Get the object in question
|
# Get the object in question
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
|
|
||||||
# Get queryset and filter out non-related categories
|
# Get queryset and filter out non-related categories
|
||||||
queryset = (
|
full_set = self.get_queryset()
|
||||||
self.get_queryset()
|
obj_topic = get_help_category(obj)
|
||||||
.filter(db_help_category=obj.db_help_category)
|
topic_set = []
|
||||||
.order_by(Lower("db_key"))
|
for entry in full_set:
|
||||||
)
|
entry_topic = get_help_category(entry)
|
||||||
context["topic_list"] = queryset
|
if entry_topic.lower() == obj_topic.lower():
|
||||||
|
topic_set.append(entry)
|
||||||
|
context["topic_list"] = topic_set
|
||||||
|
|
||||||
|
# log_info(f'topic_set: {topic_set}')
|
||||||
|
|
||||||
# Find the index position of the given obj in the queryset
|
# Find the index position of the given obj in the queryset
|
||||||
objs = list(queryset)
|
objs = list(topic_set)
|
||||||
for i, x in enumerate(objs):
|
for i, x in enumerate(objs):
|
||||||
if obj is x:
|
if obj is x:
|
||||||
break
|
break
|
||||||
|
|
@ -119,12 +284,18 @@ class HelpDetailView(HelpMixin, EvenniaDetailView):
|
||||||
context["topic_previous"] = None
|
context["topic_previous"] = None
|
||||||
|
|
||||||
# Format the help entry using HTML instead of newlines
|
# Format the help entry using HTML instead of newlines
|
||||||
|
text = 'Failed to find entry.'
|
||||||
|
if inherits_from(obj, "evennia.commands.command.Command"):
|
||||||
|
text = obj.__doc__
|
||||||
|
elif inherits_from(obj, "evennia.help.models.HelpEntry"):
|
||||||
text = obj.db_entrytext
|
text = obj.db_entrytext
|
||||||
|
elif inherits_from(obj, "evennia.help.filehelp.FileHelpEntry"):
|
||||||
|
text = obj.entrytext
|
||||||
text = text.replace("\r\n\r\n", "\n\n")
|
text = text.replace("\r\n\r\n", "\n\n")
|
||||||
text = text.replace("\r\n", "\n")
|
text = text.replace("\r\n", "\n")
|
||||||
text = text.replace("\n", "<br />")
|
text = text.replace("\n", "<br />")
|
||||||
context["entry_text"] = text
|
context["entry_text"] = text
|
||||||
|
log_info('get_context_data success')
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
|
|
@ -136,27 +307,33 @@ class HelpDetailView(HelpMixin, EvenniaDetailView):
|
||||||
entry (HelpEntry): HelpEntry requested in the URL.
|
entry (HelpEntry): HelpEntry requested in the URL.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
log_info('get_object start')
|
||||||
# Get the queryset for the help entries the user can access
|
# Get the queryset for the help entries the user can access
|
||||||
if not queryset:
|
if not queryset:
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
|
|
||||||
# Find the object in the queryset
|
# get the category and topic requested
|
||||||
category = slugify(self.kwargs.get("category", ""))
|
category = slugify(self.kwargs.get("category", ""))
|
||||||
topic = slugify(self.kwargs.get("topic", ""))
|
topic = slugify(self.kwargs.get("topic", ""))
|
||||||
obj = next(
|
|
||||||
(
|
# Find the object in the queryset
|
||||||
x
|
obj = None
|
||||||
for x in queryset
|
for entry in queryset:
|
||||||
if slugify(x.db_help_category) == category and slugify(x.db_key) == topic
|
# continue to next entry if the topics do not match
|
||||||
),
|
entry_topic = get_help_topic(entry)
|
||||||
None,
|
if not entry_topic.lower() == topic.replace('-', ' '):
|
||||||
)
|
continue
|
||||||
|
# if the category also matches, object requested is found
|
||||||
|
entry_category = get_help_category(entry)
|
||||||
|
if entry_category.lower() == category.replace('-', ' '):
|
||||||
|
obj = entry
|
||||||
|
break
|
||||||
|
|
||||||
# Check if this object was requested in a valid manner
|
# Check if this object was requested in a valid manner
|
||||||
if not obj:
|
if not obj:
|
||||||
return HttpResponseBadRequest(
|
return HttpResponseBadRequest(
|
||||||
"No %(verbose_name)s found matching the query"
|
f"No ({category}/{topic})s found matching the query"
|
||||||
% {"verbose_name": queryset.model._meta.verbose_name}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
log_info(f'get_obj returning {obj}')
|
||||||
return obj
|
return obj
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue