14.3.119. crate_anon.crateweb.core.utils
crate_anon/crateweb/core/utils.py
Copyright (C) 2015, University of Cambridge, Department of Psychiatry. Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CRATE.
CRATE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CRATE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CRATE. If not, see <https://www.gnu.org/licenses/>.
Core utility functions for the web interface.
- class crate_anon.crateweb.core.utils.JavascriptBranchNode(text: str, children: List[JavascriptTreeNode] | None = None, branch_class: str = 'caret', child_ul_class: str = 'nested')[source]
Represents a leaf node of a
JavascriptTree
, i.e. one that has children but does not itself perform an action.- __init__(text: str, children: List[JavascriptTreeNode] | None = None, branch_class: str = 'caret', child_ul_class: str = 'nested') None [source]
- Parameters:
text – text to display
children – children of this node
branch_class – CSS class for the branch with caret/indicator
child_ul_class – CSS class for the sublist with the children
- add_child(child: JavascriptTreeNode) None [source]
Adds a child at the end of our list.
- class crate_anon.crateweb.core.utils.JavascriptLeafNode(text: str, action_html: str)[source]
Represents a leaf node of a
JavascriptTree
, i.e. one that launches some action.
- class crate_anon.crateweb.core.utils.JavascriptTree(tree_id: str, child_id_prefix: str, children: List[JavascriptTreeNode] | None = None, tree_class: str = 'tree')[source]
Represents the root node of an expanding tree implemented via Javascript.
Demo:
# Django debugging preamble import os import django os.environ['DJANGO_SETTINGS_MODULE'] = 'crate_anon.crateweb.config.settings' django.setup() from crate_anon.crateweb.core.utils import ( JavascriptBranchNode, JavascriptLeafNode, JavascriptTree, ) t = JavascriptTree( tree_id="my_tree", child_id_prefix="my_tree_child_", children=[ JavascriptBranchNode("RiO", [ JavascriptLeafNode("Clinical Documents", "<p>Clinical docs</p>"), JavascriptLeafNode("Progress Notes", "<p>Prog notes</p>"), ]), JavascriptLeafNode("Test PDF", "<p>Test a PDF</p>"), ] ) print(t.html()) print(t.js_str_html()) print(t.js_data())
- __init__(tree_id: str, child_id_prefix: str, children: List[JavascriptTreeNode] | None = None, tree_class: str = 'tree') None [source]
- Parameters:
tree_id – CSS ID for this tree
child_id_prefix – CSS ID prefix for children
children – child nodes
tree_class – CSS class for this tree
- add_child(child: JavascriptTreeNode) None [source]
Adds a child at the end of our list.
- js_str_html() str [source]
Returns HTML for this tree, as a quoted Javascript string, for embedding in Javascript code directly.
- property tree_id: str
Synonym for
node_id
for the root node.
- class crate_anon.crateweb.core.utils.JavascriptTreeNode(text: str = '', node_id: str = '', children: List[JavascriptTreeNode] | None = None)[source]
Represents a node of a
JavascriptTree
.- __init__(text: str = '', node_id: str = '', children: List[JavascriptTreeNode] | None = None) None [source]
- Parameters:
text – text to display
node_id – CSS node ID (only the root node will use this mechanism; the rest will be autoset by the root node)
children – child nodes, if any
- gen_descendants() Generator[JavascriptTreeNode, None, None] [source]
Yields all descendants, recursively.
- crate_anon.crateweb.core.utils.get_friendly_date(date: datetime) str [source]
Returns a string form of a date/datetime.
- crate_anon.crateweb.core.utils.guess_mimetype(filename: str, default: str | None = None) str | None [source]
Guesses a file’s MIME type (HTTP Content-Type) from its filename.
- Parameters:
filename – filename
default – value to return if guessing fails
- crate_anon.crateweb.core.utils.is_clinician(user: auth.User) bool [source]
Is the user a clinician?
- crate_anon.crateweb.core.utils.is_developer(user: auth.User) bool [source]
Is the user a developer?
(Developers are a subset of superusers.)
- crate_anon.crateweb.core.utils.is_superuser(user: auth.User) bool [source]
Is the user a superuser?
Function for use with a decorator, e.g.
@user_passes_test(is_superuser) def some_view(request: HttpRequest) -> HttpResponse: pass
Superuser equates to Research Database Manager.
- crate_anon.crateweb.core.utils.javascript_quoted_string_from_html(html: str) str [source]
Takes some HTML, which may be multiline, and makes it into a single quoted Javascript string, for when we want to muck around with the DOM.
We elect to use double-quotes.
- crate_anon.crateweb.core.utils.paginate(request: HttpRequest, all_items: QuerySet | List[Any], per_page: int | None = None) Page [source]
Paginate a list or a Django QuerySet.
- Parameters:
request – the
django.http.request.HttpRequest
all_items – a list or a
django.db.models.QuerySet
per_page – number of items per page
- Returns:
a
django.core.paginator.Page
- crate_anon.crateweb.core.utils.site_absolute_url(path: str) str [source]
Returns an absolute URL for the site, given a relative part. Use like:
url = site_absolute_url(static('red.png')) # ... determined in part by STATIC_URL. url = site_absolute_url(reverse(UrlNames.CLINICIAN_RESPONSE, args=[self.id])) # ... determined by SCRIPT_NAME or FORCE_SCRIPT_NAME # ... which is context-dependent: see below
We need to generate links to our site outside the request environment, e.g. for inclusion in e-mails, even when we’re generating the e-mails offline via Celery. There’s no easy way to do this automatically (site path information comes in only via requests), so we put it in the settings.
See also:
IMPORTANT
BEWARE:
reverse()
will produce something different inside a request and outside it.So the only moderately clean way of doing this is to do this in the Celery backend jobs, for anything that uses Django URLs (e.g.
reverse()
) – NOT necessary for anything using only static URLs (e.g. pictures in PDFs).from django.conf import settings from django.urls import set_script_prefix set_script_prefix(settings.FORCE_SCRIPT_NAME)
But that does at least mean we can use the same method for static and Django URLs.
- crate_anon.crateweb.core.utils.string_time_now() str [source]
Returns the current time in short-form ISO-8601 UTC, for filenames.
- crate_anon.crateweb.core.utils.url_with_querystring(path: str, querydict: QueryDict | None = None, **kwargs: Any) str [source]
Add GET arguments to a URL from named arguments or a QueryDict.
- Parameters:
path – a base URL path
querydict – a
django.http.QueryDict
**kwargs – as an alternative to the
querydict
, we can usekwargs
as a dictionary of query attribute-value pairs
- Returns:
the URL with query parameters
Note
This does not currently sort query parameters. Doing that might be slightly advantageous for caching, i.e. to ensure that “path?a=1&b=2” is treated as identical to “path?b=2&a=1”. However, it is legal for servers to treat them as ordered. See https://stackoverflow.com/questions/43893853/http-cache-control-and-params-order.