Utilities¶
In the following sections, the most important functions, classes, and exception classes are mentioned and explained. This covers everything that is used in the “institute” app. It should give you a solid starting point for creating an own institute app. Nevertheless, the utility modules contain even more functions and classes.
Common helpers¶
Generating responses¶
The following names are found in the module jb_common.utils.base
.
- exception JSONRequestException(error_number, error_message)¶
Exception which is raised if a JSON response was requested and an error in the submitted data occured. This will result in an HTTP 422 response with a JSON-encoded
(error code, error message)
body. For example, in a JSON-only view function, you might say:if not request.user.is_superuser: raise JSONRequestException(6, "Only admins can access this ressource.")
The ranges for the error codes are:
- 0–999
special codes, codes common to all applications, and JuliaBase-common
- 1000–1999
JuliaBase-samples
- 2000–2999
institute-specific extensions to JuliaBase-samples
- 3000–3999
JuliaBase-kicker
The complete table with the error codes is in the main
__init__.py
of the respective app.
- is_json_requested(request)¶
Tests whether the current request should be answered in JSON format instead of HTML. Typically this means that the request was made by the JuliaBase Remote Client or by JavaScript code.
- Parameters
request (HttpRequest) – the current HTTP Request object
- Returns
whether the request should be answered in JSON
- Return type
bool
- respond_in_json(value)¶
The communication with the JuliaBase Remote Client or to AJAX clients should be done without generating HTML pages in order to have better performance. Thus, all responses are Python objects, serialised in JSON notation.
The views that can be accessed by the Remote Client/AJAX as well as normal browsers should distinguish between both by using
is_json_requested
.- Parameters
value (
object
(an arbitrary Python object)) – the data to be sent back to the client that requested JSON.- Returns
the HTTP response object
- Return type
HttpResponse
- static_response(stream, served_filename=None, content_type=None)¶
Serves a bytes string as static content.
- Parameters
stream (file-like object) – the content to be served
served_filename (str) – the filename the should be transmitted; if given, the response will be an “attachment”
content_type (str) – the MIME type of the content
- Returns
the HTTP response with the static file
- Rype
django.http.HttpResponse
The following name is found in the module samples.utils.views
.
- successful_response(request, success_report=None, view=None, kwargs={}, query_string='', forced=False, json_response=True)¶
After a POST request was successfully processed, there is typically a redirect to another page – maybe the main menu, or the page from where the add/edit request was started.
The latter is appended to the URL as a query string with the
next
key, e.g.:/juliabase/5-chamber_deposition/08S-410/edit/?next=/juliabase/samples/08S-410a
This routine generated the proper HttpResponse object that contains the redirection. It always has HTTP status code 303 (“see other”).
If the request came from the JuliaBase Remote Client, the response is a pickled
json_response
. (Normally, a simpleTrue
.)- Parameters
request (HttpRequest) – the current HTTP request
success_report (str) – an optional short success message reported to the user on the next view
view (str) – the view name to redirect to; defaults to the main menu page (same when
None
is given)kwargs (dict) – group parameters in the URL pattern that have to be filled
query_string (str) – the quoted query string to be appended, without the leading
"?"
forced (bool) – If
True
, go toview
even if a “next” URL is available. Defaults toFalse
. Seebulk_rename.bulk_rename
for using this option to generate some sort of nested forwarding.json_response (
object
) – object which is to be sent as a pickled response to the remote client; defaults toTrue
.
- Returns
the HTTP response object to be returned to the view’s caller
- Return type
HttpResponse
Miscellaneous¶
The following names are found in the module samples.utils.views
.
- convert_id_to_int(process_id)¶
If the user gives a process ID via the browser, it must be converted to an integer because this is what’s stored in the database. (Well, actually SQL gives a string, too, but that’s beside the point.) This routine converts it to a real integer and tests also for validity (not for availability in the database).
- Parameters
process_id (str) – the pristine process ID as given via the URL by the user
- Returns
the process ID as an integer number
- Return type
int
- Raises
Http404 – if the process_id didn’t represent an integer number.
- table_export(request, data, label_column_heading)¶
Helper function which does almost all work needed for a CSV table export view. This is not a view per se, however, it is called by views, which have to do almost nothing anymore by themselves. See for example
sample.export
.This function return the data in JSON format if this is requested by the
Accept
header field in the HTTP request.- Parameters
request (HttpRequest) – the current HTTP Request object
data (
samples.data_tree.DataNode
) – the root node of the data treelabel_column_heading (str) – Description of the very first column with the table row headings, see
generate_table_rows
.
- Returns
the HTTP response object or a tuple with all needed forms to create the export view
- Return type
HttpResponse or tuple of django.forms.Form
The following names are found in the module jb_common.utils.base
.
- get_really_full_name(user)¶
Unfortunately, Django’s
get_full_name
method for users returns the empty string if the user has no first and surname set. However, it’d be sensible to use the login name as a fallback then. This is realised here.- Parameters
user (django.contrib.auth.models.User) – the user instance
- Returns
The full, human-friendly name of the user
- Return type
str
- check_markdown(text)¶
Checks whether the Markdown input by the user contains only permitted syntax elements. I forbid images and headings so far.
- Parameters
text – the Markdown input to be checked
- Raises
ValidationError – if the
text
contained forbidden syntax elements.
- help_link(link)¶
Function decorator for views functions to set a help link for the view. The help link is embedded into the top line in the layout, see the template
base.html
. The default templatejb_base.html
prepends"http://www.juliabase.org/"
. But you may change that by overriding thehelp_link
block in your ownjb_base.html
.- Parameters
link (str) – the relative URL to the help page.
- send_email(subject, content, recipients, format_dict=None)¶
Sends one email to a user. Both subject and content are translated to the recipient’s language. To make this work, you must tag the original text with a dummy
_
function in the calling content, e.g.:_ = lambda x: x send_mail(_("Error notification"), _("An error has occured."), user) _ = gettext
If you need to use string formatting à la
"Hello {name}".format(name=user.name)
you must pass a dictionary like
{"name": user.name}
to this function. Otherwise, translating wouldn’t work.- Parameters
subject (str) – the subject of the email
content (str) – the content of the email; it may contain substitution tags
recipients – the recipients of the email
format_dict (dict mapping str to str) – the substitions used for the
format
string method for both the subject and the content
- round(value, digits)¶
Method for rounding a numeric value to a fixed number of significant digits.
- Parameters
value (float) – the numeric value
digit – number of significant digits
- Returns
rounded value
- Return type
str
- generate_permissions(permissions, class_name)¶
Auto-generates model permissions. It may be used in physical process classes – but not only there – like this:
class Meta(samples.models.PhysicalProcess.Meta): permissions = generate_permissions( {"add", "change", "view_every", "edit_permissions"}, "ModelClassName")
- Parameters
permissions (set of str) – The permissions to generate. Possible values are
"add"
,"change"
,"view_every"
, and"edit_permissions"
.class_name (str) – python class name of the model class, e.g.
"LayerThicknessMeasurement"
.
- Returns
the permissions tuple
- Return type
tuple of (str, str)
Feed reporting¶
The following name is found in the module samples.utils.views
.
- class Reporter(originator)¶
This class contains all feed-generating routines as methods. Their names start with
report_...
. The main reason for putting them into a class is that this class assures that no user gets two feed entries. Therefore, if you want to report a certain database change to the users, create an instance ofReporter
and call all methods that are related to the database change. Call the most meaningful method first, and the most general last. For example, when changing the data of a sample, the respective view calls the following methods in this order:report_new_responsible_person_samples report_changed_sample_topic report_edited_samples
Of course, the first two are only called if the respective data change really happend. Thus, the new responsible person is signalled first, then all people about a possible topic change, and if this didn’t happen, all so-far un-signalled users get a general message about changed sample data.
If you want to signal something to all possibly interested users, no matter on which feed entries they already have received, just create a new instance of
Reporter
.Mostly, you can call the method directly without binding the instance of
Reporter
to a name, as in:feed_utils.Reporter(request.user).report_result_process( result, edit_description=None)
- Variables
interested_users – all users that get informed with the next generated feed entry by a call to
__connect_with_users
already_informed_users – All users who have already received a feed entry from this instance of
Reporter
. They won’t get a second entry.originator – the user responsible for the databse change reported by the feed entry of this instance of
Reporter
.
Class constructor.
- Parameters
originator (django.contrib.auth.models.User) – the user who did the database change to be reported; almost always, this is the currently logged-in user
- report_changed_sample_series_topic(sample_series, old_topic, edit_description)¶
Generate a feed entry about a topic change for a sample series. All members of the former topic and the new topic are informed. Note that it is possible that further things were changed in the sample series at the same time (reponsible person, samples …). They should be mentioned in the description by the one who changed it.
- Parameters
sample_series (list of
samples.models.SampleSeries
) – the sample series that went into a new topicold_topic (
jb_common.models.Topic
) – the old topic of the samples; may beNone
if they weren’t in any topic beforeedit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the sample series (besides the change of the topic). Its keys correspond to the fields ofEditDescriptionForm
.
- report_changed_sample_topic(samples, old_topic, edit_description)¶
Generate a feed entry about a topic change for sample(s). All members of the former topic (if any) and the new topic are informed. Note that it is possible that further things were changed in the sample(s) at the same time (reponsible person, purpose …). They should be mentioned in the description by the one who changed it.
- Parameters
samples (list of
samples.models.Sample
) – the samples that went into a new topicold_topic (
jb_common.models.Topic
) – the old topic of the samples; may beNone
if they weren’t in any topic beforeedit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the samples (besides the change of the topic). Its keys correspond to the fields ofEditDescriptionForm
.
- report_changed_topic_membership(users, topic, action)¶
Generate one feed entry for changed topic memberships, i.e. added or removed users in a topic.
- Parameters
users (iterable of django.contrib.auth.models.User) – the affected users
topic (
jb_common.models.Topic
) – the topic whose memberships have changedaction (str) – what was done;
"added"
for added users,"removed"
for removed users
- report_copied_my_samples(samples, recipient, comments)¶
Generate a feed entry for sample that one user has copied to another user’s “My Samples” list.
- Parameters
samples (list of
samples.models.Sample
) – the samples that were copied to another userrecipient (django.contrib.auth.models.User) – the other user who got the samples
comments (str) – a message from the sender to the recipient
- report_deleted_process(process)¶
Generate a feed entry about a deletion of a process.
- Parameters
process (
samples.models.Process
) – the process that was deleted
- report_deleted_sample(sample)¶
Generate a feed entry about a deletion of a sample. All users who are allowed to see the sample and who have the sample on their “My Samples” list are informed.
- Parameters
sample (
samples.models.Sample
) – the sample that was deleted
- report_edited_sample_series(sample_series, edit_description)¶
Generate a feed entry about an edited of sample series. All users who have watches samples in this series are informed, including the currently responsible person (in case that it is not the originator).
- Parameters
sample_series (list of
samples.models.SampleSeries
) – the sample series that was editededit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the sample series. Its keys correspond to the fields ofEditDescriptionForm
.
- report_edited_samples(samples, edit_description)¶
Generate a feed entry about a general edit of sample(s). All users who are allowed to see the sample and who have the sample on their “My Samples” list are informed.
- Parameters
samples (list of
samples.models.Sample
) – the samples that were editededit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the samples. Its keys correspond to the fields ofEditDescriptionForm
.
- report_new_responsible_person_sample_series(sample_series, edit_description)¶
Generate a feed entry for a sample series that changed their currently responsible person. This feed entry is only sent to that new responsible person. Note that it is possible that further things were changed in the sample series at the same time (topic, samples …). They should be mentioned in the description by the formerly responsible person.
- Parameters
sample_series (list of
samples.models.SampleSeries
) – the sample series that got a new responsible personedit_description (dict mapping str to
object
) – Dictionary containing data about what was edited in the sample series (besides the change of the responsible person). Its keys correspond to the fields ofEditDescriptionForm
.
- report_new_responsible_person_samples(samples, edit_description)¶
Generate a feed entry for samples that changed their currently responsible person. This feed entry is only sent to that new responsible person. Note that it is possible that further things were changed in the sample(s) at the same time (topic, purpose …). They should be mentioned in the description by the formerly responsible person.
- Parameters
samples (list of
samples.models.Sample
) – the samples that got a new responsible personedit_description (dict mapping str to
object
) – Dictionary containing data about what was edited in the samples (besides the change of the responsible person). Its keys correspond to the fields ofEditDescriptionForm
.
- report_new_sample_series(sample_series)¶
Generate one feed entry for a new sample series.
- Parameters
sample_series (
samples.models.SampleSeries
) – the sample series that was added
- report_new_samples(samples)¶
Generate one feed entry for new samples. If more than one sample is in the given list, they are assumed to have been generated at the same time, so they should share the same topic and purpose.
If the sample or samples are not in a topic, no feed entry is generated (because nobody listens).
- Parameters
samples (list of
samples.models.Sample
) – the samples that were added
- report_physical_process(process, edit_description=None)¶
Generate a feed entry for a physical process (deposition, measurement, etching etc) which was recently edited or created. If the process is still unfinished, nothing is done.
- Parameters
process (
samples.models.Process
) – the process which was added/edited recentlyedit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the process. Its keys correspond to the fields ofEditDescriptionForm
.None
if the process was newly created.
- report_removed_task(task)¶
Generate one feed for a removed task. It is called immediately before the task is actually deleted.
- Parameters
task (
models.Task
) – the to-be-deleted task
- report_result_process(result, edit_description=None)¶
Generate a feed entry for a result process which was recently edited or created.
- Parameters
result (
samples.models.Result
) – the result process which was added/edited recentlyedit_description (dict mapping str to
object
) – The dictionary containing data about what was edited in the result. Its keys correspond to the fields ofEditDescriptionForm
.None
if the process was newly created.
- report_sample_split(sample_split, sample_completely_split)¶
Generate a feed entry for a sample split.
- Parameters
sample_split (
samples.models.SampleSplit
) – sample split that is to be reportedsample_completely_split (bool) – whether the sample was completely split, i.e. no piece of the parent sample is left
- report_status_message(process_class, status_message)¶
Generate one feed entry for new status messages for physical processes.
- Parameters
process_class (django.contrib.contenttypes.models.ContentType) – the content type of the physical process whose status has changed
status_message (
samples.models.StatusMessage
) – the status message for the physical process
- report_task(task, edit_description=None)¶
Generate one feed entry for a new task or an edited task.
- Parameters
task (
models.Task
) – the task that was created or editededit_description (dict mapping str to
object
orNone
) – The dictionary containing data about what was edited in the task. Its keys correspond to the fields ofEditDescriptionForm
.None
if the task was newly created.
- report_withdrawn_status_message(process_class, status_message)¶
Generate one feed entry for a withdrawn status message for physical processes.
- Parameters
process_class (django.contrib.contenttypes.models.ContentType) – the content type of the physical process one of whose statuses was withdrawn
status_message (
samples.models.StatusMessage
) – the status message for the physical process
Form field classes¶
The following names are found in the module jb_common.utils.views
.
- class UserField(*, choices=(), **kwargs)¶
Form field class for the selection of a single user. This can be the new currently responsible person for a sample, or the person you wish to send “My Samples” to.
- set_users(user, additional_user=None)¶
Set the user list shown in the widget. You must call this method (or
set_users_without()
) in the constructor of the form in which you use this field, otherwise the selection box will remain emtpy. The selection list will consist of all currently active users, plus the given additional user if any.- Parameters
user (django.contrib.auth.models.User) – Thr user who wants to see the user list
additional_user (django.contrib.auth.models.User) – Optional additional user to be included into the list. Typically, it is the current user for the process to be edited.
- set_users_without(user, excluded_user)¶
Set the user list shown in the widget. You must call this method (or
set_users()
) in the constructor of the form in which you use this field, otherwise the selection box will remain emtpy. The selection list will consist of all currently active users, minus the given user.- Parameters
user – Thr user who wants to see the user list
excluded_user (django.contrib.auth.models.User) – User to be excluded from the list. Typically, it is the currently logged-in user.
- class MultipleUsersField(*args, **kwargs)¶
Form field class for the selection of zero or more users. This can be the set of members for a particular topic.
- set_users(user, additional_users=[])¶
Set the user list shown in the widget. You must call this method in the constructor of the form in which you use this field, otherwise the selection box will remain emtpy. The selection list will consist of all currently active users, plus the given additional users if any.
- Parameters
user – Thr user who wants to see the user list
additional_users (iterable of django.contrib.auth.models.User) – Optional additional users to be included into the list. Typically, it is the current users for the topic whose memberships are to be changed.
- class TopicField(*, choices=(), **kwargs)¶
Form field class for the selection of a single topic. This can be the topic for a sample or a sample series, for example.
- set_topics(user, additional_topic=None)¶
Set the topic list shown in the widget. You must call this method in the constructor of the form in which you use this field, otherwise the selection box will remain emtpy. The selection list will consist of all currently active topics, plus the given additional topic if any. The “currently active topics” are all topics with at least one active user amongst its members.
- Parameters
user (django.contrib.auth.models.User) – the currently logged-in user
additional_topic (
jb_common.models.Topic
) – Optional additional topic to be included into the list. Typically, it is the current topic of the sample, for example.
Form classes¶
The following names are found in the module samples.utils.views
.
- class ProcessForm(user, *args, **kwargs)¶
Abstract model form class for processes. It ensures that timestamps are not in the future, and that comments contain only allowed Markdown syntax.
Moreover, it defines a field “combined_operator” of the type
OperatorField
. In the HTML template, you should offer this field to non-staff, and the usual operator/external operator to staff.- Parameters
user (django.contrib.auth.models.User) – the currently logged-in user
- is_referentially_valid(samples_form)¶
Test whether the forms are consistent with each other and with the database. In its current form, it only checks whether the sample is still “alive” at the time of the measurement.
- Parameters
samples_form (
SampleSelectForm
orMultipleSamplesSelectForm
) – a bound samples selection form- Returns
whether the forms are consistent with each other and the database
- Return type
bool
- class DepositionForm(user, data=None, **kwargs)¶
Model form for depositions (not their layers).
- Parameters
user (django.contrib.auth.models.User) – the currently logged-in user
- is_referentially_valid(samples_form)¶
Test whether the forms are consistent with each other and with the database. In its current form, it only checks whether the sample is still “alive” at the time of the measurement.
- Parameters
samples_form (
SampleSelectForm
orMultipleSamplesSelectForm
) – a bound samples selection form- Returns
whether the forms are consistent with each other and the database
- Return type
bool
- class SampleSelectForm(user, process_instance, preset_sample, *args, **kwargs)¶
Form for the sample selection field. You can only select one sample per process (in contrast to depositions).
- Parameters
user (django.contrib.auth.models.User) – the current user
process_instance (
samples.models.Process
) – the process instance to be edited, orNone
if a new is about to be createdpreset_sample (
samples.models.Sample
) – the sample to which the process should be appended when creating a new process; seeutils.extract_preset_sample
- class DepositionSamplesForm(user, deposition, preset_sample, data=None, **kwargs)¶
Form for the list selection of samples that took part in the deposition. This form has the special behaviour that it prevents changing the samples when editing an existing process.
- class EditDescriptionForm(*args, **kwargs)¶
Form for letting the user enter a short description of the changes they made.
Plots¶
The following names are found in the module samples.utils.plots
.
- exception PlotError¶
Raised if an error occurs while generating a plot. Usually, it is raised in
samples.models.Process.draw_plot()
and caught insamples.views.plots.show_plot()
.
- read_plot_file_beginning_at_line_number(filename, columns, start_line_number, end_line_number=None, separator=None)¶
Read a datafile and returns the content of selected columns beginning at start_line_number. You shouldn’t use this function directly. Use the specific functions instead.
- Parameters
filename (str) – full path to the data file
columns (list of int) – the columns that should be read.
start_line_number (int) – the line number where the data starts
end_line_number (int or None) – the line number where the record should end. The default is
None
, means till end of file.separator (str or None) – the separator which separates the values from each other. Default is
None
- Returns
List of all columns. Every column is represented as a list of floating point values.
- Return type
list of list of float
- Raises
PlotError – if something wents wrong with interpreting the file (I/O, unparseble data)
- read_plot_file_beginning_after_start_value(filename, columns, start_value, end_value='', separator=None)¶
Read a datafile and return the content of selected columns after the start_value was detected. You shouldn’t use this function directly. Use the specific functions instead.
- Parameters
filename (str) – full path to the data file
columns (list of int) – the columns that should be read.
start_value (str) – the start_value indicates the line after the data should be read
end_value (str) – the end_value marks the line where the record should end. The default is the empty string
separator (str or None) – the separator which separates the values from each other. Default is
None
- Returns
List of all columns. Every column is represented as a list of floating point values.
- Return type
list of list of float
- Raises
PlotError – if something wents wrong with interpreting the file (I/O, unparseble data)
URLs¶
The following name is found in the module samples.utils.urls
.
- class PatternGenerator(url_patterns, views_prefix, app_label=None)¶
This class helps to build URL pattern lists for physical processes. You instantiate it once in your URLconf file. Then, you add URLs by calling
physical_process
for every physical process:pattern_generator = PatternGenerator(urlpatterns, "institute.views.samples") pattern_generator.deposition("ClusterToolDeposition", views={"add", "edit"}) pattern_generator.deposition("FiveChamberDeposition", "5-chamber_depositions") pattern_generator.physical_process("PDSMeasurement", "number") pattern_generator.physical_process("Substrate", views={"edit"})
Important: Various places of JuliaBase assume that the URL patterns of physical processes reside in a namespace which has the same name as the app which holds the associated model classes. So take care that this is the case!
- Parameters
url_patterns (list of
path()
orre_path()
instances) – The URL patterns to populate in situ.views_prefix (str) – the prefix for the view functions as a Python path, e.g.
"my_app.views.samples"
app_label (str) – The label of the app to which the generated URLs will belong to. Defaults to the first component of
views_prefix
.
- deposition(class_name, url_name=None, views={'add', 'edit', 'lab_notebook'})¶
Add URLs for the views of the deposition process
class_name
. This is a shorthand forphysical_process
with defaults optimized for depositions:identifying_field
is"number"
, and the views include a lab notebook.- Parameters
class_name (str) – Name of the deposition class, e.g.
"FiveChamberDeposition"
.url_name (str) – The URL path component to be used for this deposition. By default, this is the class name converted to underscores notation, with an “s” appended, e.g.
"thickness_measurements"
.views (set of str) – The view functions for which URLs should be generated. You may choose from
"add"
,"edit"
,"custom_show"
, and"lab_notebook"
.
- physical_process(class_name, identifying_field=None, url_name=None, views={'add', 'edit'})¶
Add URLs for the views of the physical process
class_name
. For the “add” and the “edit” view, anedit(request, process_class_name_id)
function must exist. In case of “add”,None
is passed as the second parameter. For the “custom show” view, ashow(request, process_class_name_id)
function must exist. If there is anidentifying_field
, this is used for the second parameter name instead. If no URL for a custom show view is requested, a default one is generated using a generic view function (which is mostly sufficient).- Parameters
class_name (str) – Name of the physical process class, e.g.
"ThicknessMeasurement"
.identifying_field (str) – If applicable, name of the model field which serves as “poor man’s” primary key. If not given, the field name is derived from the model’s
JBMeta
class, and if this fails,id
is used. This parameter is deprecated and will be removed in JuliaBase 1.2.url_name (str) – The URL path component to be used for this process. By default, this is the class name converted to underscores notation, with an “s” appended, e.g.
"thickness_measurements"
. It may contain slashs.views (set of str) – The view functions for which URLs should be generated. You may choose from
"add"
,"edit"
,"custom_show"
, and"lab_notebook"
.