Record fields#
Record fields are form fields that choose a project, dataset, sample, measurement, person or organization by searching for it. Three more fields in the same module choose a publication, tags or a ROR entry. They are in fairdm.contrib.autocomplete.fields, and each sends its searches to an address that FairDM provides and answers with the records the person using the field may reach. This page lists the fields, their arguments, the results and addresses they use, and their limits. For the steps to put one on a form, see How to add a record field to a form. For the reasoning behind what they offer, see How record fields decide what to offer.
The fields#
Each kind of record has a single field and a multiple field. Both are built by record_fields() and share the arguments below.
Single field |
Multiple field |
Chooses |
Scopes |
Default scope |
|---|---|---|---|---|
|
|
A project |
|
|
|
|
A dataset |
|
|
|
|
A sample |
|
|
|
|
A measurement |
|
|
|
|
A person |
|
|
|
|
An organization |
|
|
from django import forms
from fairdm.contrib.autocomplete.fields import (
DatasetChoiceField,
OrganizationMultipleChoiceField,
PersonChoiceField,
ProjectMultipleChoiceField,
SampleChoiceField,
)
from myportal.models import CoreSample # a sample type of your portal
class EveryKindForm(forms.Form):
dataset = DatasetChoiceField(scope="edit")
projects = ProjectMultipleChoiceField(scope="public")
core_sample = SampleChoiceField(type=CoreSample)
sample = SampleChoiceField(depends_on="dataset")
person = PersonChoiceField()
organizations = OrganizationMultipleChoiceField()
Arguments#
A record field takes the arguments of Django’s ModelChoiceField or ModelMultipleChoiceField and five more. The field decides what it offers, so you do not pass a queryset.
Argument |
Type |
Default |
What it does |
What it accepts |
|---|---|---|---|---|
|
|
The field’s default scope |
Sets what the person must be able to do with a record for the field to offer it. |
|
|
|
— |
Offers the records that person is credited on, and their private ones only when they are the person using the field. |
A person, or a person’s primary key. Cannot be given with |
|
model class |
— |
Offers and accepts that type only. |
A subclass of the kind’s model, for samples and measurements. |
|
|
— |
Offers only the records that belong to the value chosen in the named field of the same form. |
|
|
|
— |
Lists the records that belong to the value chosen in the named field first, in a group of their own, and offers the rest after them. It narrows nothing. |
The same names as |
A field raises ValueError when it is created if:
scopeis not one the kind offers,owneris given withscope, or to a person or organization field,depends_onorprefernames a field the kind’s address does not allow,typeis not a subclass of the kind’s model, or the kind is a project, dataset, person or organization.
Dependent fields#
A field with depends_on follows the field it names.
In the browser, it searches only the records of the value chosen in the other field and clears its own choice when that value changes.
On submit, it reads the value of the other field from the form’s own data and accepts only a record that belongs to it. Any other record is refused with
invalid_choice. The page’s address plays no part.When the other field has no value, the field is not narrowed.
Preferred fields#
A field with prefer lists the records that belong to the value of the field it names under a heading of their own, such as “Samples in this dataset”. It accepts the same records whatever the other field holds. When the other field has no value, the records are listed as usual.
Scopes#
Scope |
Offers |
|---|---|
|
Public records, to everyone, signed in or not. |
|
Public records, and the records the person may view. |
|
Only the records the person may edit. A person who is not signed in is offered nothing. |
|
The records one person, named by |
A record is public when:
a project’s visibility is public,
a dataset’s visibility is public and so is its project’s, or it has no project,
a sample’s or measurement’s dataset is public and published.
A person may view or edit a record when they hold that level on it, on the project above a dataset, or on the dataset or its project above a sample or measurement. A right the portal gives on every record, as the superuser and Data Curator roles have, offers all of them. The levels are in Contribution levels and record access.
Validation#
A field accepts a value only when it would have offered that record to the same person. Any other record is refused with the error code invalid_choice.
A record that already holds a link to a record the person cannot see keeps it. The field shows the stored link as “Private record”, without a name, and accepts it when the form is saved unchanged. It never offers that record in a search.
The person is the user on the form’s
requestattribute. If the form has none, the field uses the request it was given (given_request), and then the request django-tomselect’s middleware holds for the current thread.A form built outside any request, in a script or a test, accepts what is in the field’s
querysetand nothing by default.
People and organizations#
A person and an organization are public information, so these fields offer them at the public scope only and take neither owner, depends_on nor prefer.
A person is found by name, by an alternative name, or by an ORCID iD typed exactly.
An organization is found by name, by an alternative name, or by a ROR identifier typed exactly.
An identifier typed exactly lists that person or organization first. A part of an identifier finds nothing.
Superusers and the anonymous placeholder account are never offered. An email address is not searched and is never part of a result.
Results come in two groups:
Kind |
First group |
Second group |
|---|---|---|
Person |
“People you have worked with”: people credited on a record the searcher can open |
“Everyone else” |
Organization |
“Your organizations”: those where the searcher has a verified affiliation that has not ended |
“Other organizations” |
A person’s row shows their picture or initials, their primary affiliation and their ORCID iD, and marks a person nobody has claimed. An organization’s row shows its city and country and no identifier.
PublicationChoiceField#
Argument |
Type |
Default |
What it does |
What it accepts |
|---|---|---|---|---|
Django’s |
Choose one publication from the portal’s literature. |
Every argument except |
The field accepts any publication that exists. A publication is found by part of its title, by part of an author’s name, or by its DOI typed exactly. A DOI typed with a doi: prefix or as an address finds the same publication. Its address is autocomplete:publication.
RorChoiceField#
RorChoiceField looks an organization up in the Research Organization Registry by name and chooses one entry. Its value is the ROR ID, or the ROR address, as the person chose it.
Argument |
Type |
Default |
What it does |
What it accepts |
|---|---|---|---|---|
Django’s |
Choose one ROR entry. |
Every argument. |
The field accepts any value in the form of a ROR ID or its address and never asks ROR to check it, so a form saves while ROR does not answer.
A value that is not in that form is refused with
invalid_choice.A field that is not required accepts an empty value.
The search starts at three characters, shows nothing for an empty search and lists at most ten active organizations, so there is one page.
When ROR does not answer, the address answers with status 503 and an empty list.
Filters#
Both filters are in fairdm.contrib.autocomplete.filters.
Filter |
Arguments |
Draws |
Default scope |
|---|---|---|---|
|
The multiple field class, |
The multiple field of one kind in a filter set |
|
|
|
|
|
Choosing several records or tags keeps the rows that point at any of them. A filter set must be built with the request, or the filter offers and accepts nothing. The list filters FairDM ships use these: the dataset list’s project filter, the sample list’s dataset filter, the measurement list’s dataset and sample filters, and the project list’s owner, contributor and tag filters. A filter generated for a registered type’s relation to a project, dataset, sample or measurement is a RecordMultipleFilter.
Results#
Each address answers with a page of results. A result carries these keys.
Key |
Holds |
Present on |
|---|---|---|
|
The record’s primary key, which the form submits. |
Records, people, organizations, publications, tags |
|
The record’s name. |
Records, people, organizations, tags |
|
|
Records |
|
A dataset’s project name, or |
Datasets |
|
The record’s type, such as “rock sample”. |
Samples, measurements |
|
The creator’s own identifier for the record. |
Samples, measurements |
|
The name of the record’s dataset. |
Samples, measurements |
|
The heading of the group the result is listed under. Absent when the page holds only public records. |
Records, people, organizations |
|
A person’s primary affiliation, an organization’s place, or a ROR entry’s kind and place. |
People, organizations, ROR |
|
|
People |
|
The publication’s title, its authors’ family names joined with commas, a number or |
Publications |
|
A ROR entry’s address and the organization’s name. |
ROR |
|
The row, drawn on the server. |
All |
Record results are grouped, in this order:
Group |
Heading |
Holds |
|---|---|---|
Preferred |
“Samples in this dataset”, and so on |
Records that match the field named by |
Own |
“Your samples” |
Records the person holds the view level on |
Public |
“Public samples” |
Public records |
Other |
“Other samples” |
Any further records a portal-wide right lets the person see |
A record appears once, in its first group. A record that matches the search text exactly is listed first. The rest follow group by group, in order of name.
Searching#
Kind |
Found by (contains, ignoring case) |
Listed first when typed exactly |
|---|---|---|
Project |
Name |
UUID |
Dataset |
Name |
UUID |
Sample |
Name, local ID, identifier value |
Local ID, UUID, identifier value |
Measurement |
Name, local ID |
Local ID, UUID |
Person |
Name, alternative names |
ORCID iD |
Organization |
Name, alternative names |
ROR identifier |
Publication |
Title, author’s name |
DOI |
Tag |
Name |
— |
Addresses#
The addresses are under the autocomplete namespace and the autocomplete/ path. The scope belongs to the address, so a request cannot widen it.
Name |
Path |
Serves |
|---|---|---|
|
|
A project, dataset, sample or measurement at |
|
|
People |
|
|
Organizations |
|
|
Publications |
|
|
Tags |
|
|
ROR entries |
The profile address takes the owner’s primary key in an owner query parameter.
Limits#
Limit |
Value |
|---|---|
Results in a page |
20, whatever page size a request names |
Last page served |
25 |
Longest search text |
100 characters, cut when longer |
Filters a request may name |
None for projects, datasets, people, organizations, publications, tags and ROR. |
Ordering a request may name |
None. An ordering is ignored. |
A search that fails |
Status 500 and an empty list |
A caller over a rate limit |
Status 429, a |
Request rates#
Each address limits a caller with four throttles. A signed-in caller is counted by account and anyone else by network address. The rate of each scope is set in REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"] and described in Settings. A scope left out uses the default on its throttle class. For why there are two limits, see How API callers are limited.
Throttle class |
Scope |
|---|---|
|
|
|
|
|
|
|
|
The throttles are in fairdm.contrib.autocomplete.throttling. To change the rates, see How to change the API rate limits.
Classes behind the fields#
A field needs none of these to work. They matter to a portal that builds a field of its own on the same address and limits.
Views, in fairdm.contrib.autocomplete.views:
Class |
Serves |
|---|---|
|
The page size, page depth, search length, filter and ordering limits, and the throttles, for every view below |
|
The base of the record views: scope, grouping and exact-match ordering |
|
Projects |
|
Datasets, taken from |
|
The base of the two views below, for records that sit inside a dataset |
|
Samples |
|
Measurements |
|
The base of the two views below, with the “near first” grouping |
|
People |
|
Organizations |
|
The portal’s literature |
|
Tags in use on records the requester may see |
|
The ROR registry |
scoped_view(view_class, scope) returns the subclass of a record view that serves one scope. RecordAutocompleteView.for_scope(scope) does the same. Each scope is its own class because django-tomselect rebuilds a view without the arguments given to as_view() when it validates a value. See ADR 0038.
from django.urls import path
from fairdm.contrib.autocomplete.views import SampleAutocompleteView, scoped_view
urlpatterns = [
path("samples/edit/", scoped_view(SampleAutocompleteView, "edit").as_view()),
]
Fields and widgets, in fairdm.contrib.autocomplete.fields:
Name |
Is |
|---|---|
|
Makes the single and the multiple field for one record view |
|
Carry the arguments, the validation through the view and the kept stored value |
|
Write the address, the dependency and the count words on the control, built on |
|
Draws the chips of |