14.3.53. crate_anon.crateweb.consent.models

crate_anon/crateweb/consent/models.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/>.


Django ORM models for the consent-to-contact system.

class crate_anon.crateweb.consent.models.CharityPaymentRecord(*args, **kwargs)[source]

A record of a payment made to charity.

exception DoesNotExist
exception MultipleObjectsReturned
class crate_anon.crateweb.consent.models.ClinicianInfoHolder(clinician_type: str, title: str, first_name: str, surname: str, email: str, signatory_title: str, is_consultant: bool, start_date: date | datetime | None = None, end_date: date | datetime | None = None, address_components: List[str] | None = None)[source]

Represents information about a clinician (relating to a patient, whose details are not held here). Also embodies information about which sort of clinician we prefer to ask about patient contact requests (via clinician_preference_order).

Python object only; not stored in the database.

__init__(clinician_type: str, title: str, first_name: str, surname: str, email: str, signatory_title: str, is_consultant: bool, start_date: date | datetime | None = None, end_date: date | datetime | None = None, address_components: List[str] | None = None) None[source]
Parameters:
  • clinician_type – one of our special strings indicating what type of clinician (e.g. care coordinator, consultant, other healthcare professional, authorized clinical team representative).

  • title – clinician’s title

  • first_name – clinician’s first name

  • surname – clinician’s surname

  • email – clinician’s e-mail address

  • signatory_title – when the clinician signs a letter, what should go under their name to say what job they do? (For example: “Consultant psychiatrist”; “Care coordinator”).

  • is_consultant – is the clinician an NHS consultant? (Relates to special legal rules regarding CTIMPs.)

  • start_date – when did this clinician’s involvement start?

  • end_date – when did this clinician’s involvement end?

  • address_components – address lines for the clinician

contactable() bool[source]

Do we have enough information to contact the clinician (electronically)?

current() bool[source]

Is the clinician currently involved (with this patient’s care)?

class crate_anon.crateweb.consent.models.ClinicianResponse(*args, **kwargs)[source]

Represents the response of a clinician to a ContactRequest that was routed to them.

exception DoesNotExist
exception MultipleObjectsReturned
classmethod create(contact_request: ContactRequest, save: bool = True) ClinicianResponse[source]

Creates a new clinician response object.

Parameters:
  • contact_request – a ContactRequest

  • save – save to the database? (Only false for debugging.)

Returns:

a ClinicianResponse

finalize_a() None[source]

Call this when the clinician completes their response.

Part A: immediate, called from the web front end, for acknowledgement.

finalize_b() None[source]

Call this when the clinician completes their response.

Part B: called by the background task processor, for the slower aspects.

get_abs_url(email_choice: str) str[source]

Returns an absolute URL representing a specific choice for the clinician.

Parameters:

email_choice – code for the clinician’s choice

Returns:

a URL

get_abs_url_maybe() str[source]

Returns an absolute URL for “clinician says tell me more”.

get_abs_url_no() str[source]

Returns an absolute URL for “clinician says no”.

get_abs_url_path() str[source]

Returns an absolute URL path to the page that lets the clinician respond for this ClinicianResponse.

This is used in the e-mail to the clinician.

get_abs_url_yes() str[source]

Returns an absolute URL for “clinician says yes”.

get_common_querydict(email_choice: str) QueryDict[source]

Returns a query dictionary that will contribute to our final URLs. That is, information about the clinician’s choice (and also a security token) that will be added to the base “response” URL path.

Parameters:

email_choice – code for the clinician’s choice

Returns:

a django.http.request.QueryDict

get_response_explanation() str[source]

Returns the human-readable description of the clinician’s response.

class crate_anon.crateweb.consent.models.ConsentMode(*args, **kwargs)[source]

Represents a consent-to-contact consent mode for a patient.

exception DoesNotExist
exception MultipleObjectsReturned
consider_withdrawal() None[source]

If required, withdraw consent for other studies.

Note that as per Major Amendment 1 to 12/EE/0407, this happens automatically, rather than having a special flag to control it.

get_confirm_traffic_to_patient_letter_html(patient_lookup_override: PatientLookup | None = None) str[source]

Letter to patient, confirming traffic-light choice.

Returns HTML for this letter, customized to the patient.

get_latest_patient_lookup() PatientLookup[source]

Returns the latest PatientLookup information (from the CRATE admin database) for this patient.

classmethod get_or_create(nhs_number: int, created_by: auth.User) ConsentMode[source]

Fetches the current ConsentMode for this patient. If there isn’t one, creates a default one and returns that.

classmethod get_or_none(nhs_number: int) ConsentMode | None[source]

Fetches the current ConsentMode for this patient. If there isn’t one, returns None.

static get_unprocessed() QuerySet[source]

Return all ConsentMode objects that need processing.

See crate_anon.crateweb.consent.tasks.process_consent_change() and process_change(), which does the work.

notify_rdbm_of_work(letter: Letter, to_researcher: bool = False) None[source]

E-mail the RDBM saying that there’s new work to do: a letter to be sent.

Parameters:
  • letterLetter

  • to_researcher – is it a letter that needs to go to a researcher, rather than to a patient?

process_change() None[source]

Called upon saving.

  • Will create a letter to patient.

  • May create a withdrawal-of-consent letter to researcher.

  • Marks the ConsentMode as having been processed.

Major Amendment 1 (Oct 2014) to 12/EE/0407: always withdraw consent and tell researchers, i.e. “active cancellation” of ongoing permission, where the researchers have not yet made contact.

classmethod refresh_from_primary_clinical_record(nhs_number: int, created_by: auth.User, source_db: str = None) List[str][source]

Checks the primary clinical record and CRATE’s own records for consent modes for this patient. If the most recent one is in the external database, copies it to CRATE’s database and marks that one as current.

This has the effect that external primary clinical records (e.g. RiO) take priority, but if there’s no record in RiO, we can still proceed.

Returns a list of human-readable decisions.

Internally, we do this:

  • Fetch the most recent record.

  • If its date is later than the most recent CRATE record:

    • create a new ConsentMode with (…, source=source_db)

    • save it

    • trigger crate_anon.crateweb.consent.tasks.process_consent_change() on commit, which might take further action

save(*args, **kwargs) None[source]

Custom save method. Ensures that only one ConsentMode has current == True for a given patient.

This is better than a get_latest_by clause, because with a flag like this, we can have a simple query that says “get the current records for all patients” – which is harder if done by date (group by patient, order by patient/date, pick last one for each patient…).

See https://stackoverflow.com/questions/1455126/unique-booleanfield-value-in-django

class crate_anon.crateweb.consent.models.ContactRequest(*args: Any, **kwargs: Any)[source]

Represents a contact request to a patient (directly or indirectly) about a study.

exception DoesNotExist
exception MultipleObjectsReturned
__init__(*args: Any, **kwargs: Any) None[source]
calc_approaches_in_past_year() None[source]

Sets approaches_in_past_year to indicate the number of approaches in the past year to this patient via CRATE.

How best to count this? Not by e.g. calendar year, with a flag that gets reset to zero annually, because you might have a limit of 5, and get 4 requests in Dec 2020 and then another 4 in Jan 2021 just after the flag resets. Instead, we count the number of requests to that patient in the past year.

classmethod create(request: HttpRequest, study: Study, request_direct_approach: bool, lookup_nhs_number: int | None = None, lookup_rid: str | None = None, lookup_mrid: str | None = None, clinician_initiated: bool = False, clinician_email: str | None = None, rdbm_to_contact_pt: bool = False, clinician_signatory_name: str | None = None, clinician_signatory_title: str | None = None) ContactRequest[source]

Create a contact request and act on it.

Parameters:
  • request – the django.http.request.HttpRequest

  • study – the Study

  • request_direct_approach – would the researchers prefer to approach the patient directly, if permitted?

  • lookup_nhs_number – NHS number to look up patient from

  • lookup_rid – research ID (RID) to look up patient from

  • lookup_mrid – master research ID (MRID) to look up patient from

  • clinician_initiated – contact request initiated by the clinician?

  • clinician_email – override the clinician email in patient_lookup

  • rdbm_to_contact_pt – should the rbdm contact the patient - for cases where the request was initiated by clinician

  • clinician_signatory_name – name of clinician for letter - if None will use PatientLookup

  • clinician_signatory_title – signatory title of clinician - if None will use PatientLookup

Returns:

a ContactRequest

decide(msg: str) None[source]

Make a note of a decision.

get_approval_email_html() str[source]

Returns HTML for a simple e-mail to the researcher attaching an approval letter.

get_approval_letter_html() str[source]

REC DOCUMENT 15. Letter to researcher approving contact.

Returns the HTML for this letter.

get_clinician_email_html(save: bool = True) str[source]

REC DOCUMENTS 09, 11, 13 (A): E-mail to clinician asking them to pass on contact request.

Parameters:

save – save the e-mail to the database? (Only false for testing.)

Returns:

HTML for this e-mail

  • When we create a URL, should we put parameters in the path, querystring, or both?

    • see notes in core/utils.py

    • In this case, we decide as follows: since we are creating a ClinicianResponse, we should use its ModelForm.

    • URL path for PK

    • querystring for other parameters, with form-based validation

get_clinician_initiated_email_html(save: bool = True) str[source]

Email to clinician confirming a clinician-initiated contact request. Will inlcude a link to the clinician pack if they do not want the RDBM to contact the patient for them. Also sets the clinician’s response.

Parameters:

save – save the e-mail to the database? (Only false for testing.)

Returns:

HTML for this e-mail

static get_clinician_involvement(consent_mode_str: str, request_direct_approach: bool) int[source]

Returns a number indicating why a clinician is involved.

Parameters:
  • consent_mode_str – consent mode in use (see ConsentMode)

  • request_direct_approach – do the researchers request direct approach to the patient, if permitted?

Returns:

an integer constant; see ContactRequest

get_clinician_pack_pdf() bytes[source]

Returns a PDF of the “clinician pack”: a cover letter, decision forms, and any other information required, customized for this request.

get_decision_form_to_pt_re_study() str[source]

Returns HTML for the form for the patient to decide about this study.

get_letter_clinician_to_pt_re_study() str[source]

Letters from clinician to patient, with decision form.

Returns the HTML for this letter.

get_mgr_admin_url() str[source]

Returns the URL for the admin site to view this ContactRequest.

get_permission_date() datetime | None[source]

When was the researcher given permission? Used for the letter withdrawing permission.

static get_unprocessed() QuerySet[source]

Return all ContactRequest objects that need processing.

See crate_anon.crateweb.consent.tasks.process_contact_request() and process_request(), which does the work.

get_withdrawal_email_html() str[source]

Returns HTML for a simple e-mail to the researcher attaching an withdrawal-of-previous-consent letter.

get_withdrawal_letter_html() str[source]

REC DOCUMENT 16. Letter to researcher notifying them of withdrawal of consent.

Returns the HTML for this letter.

Is the consent mode “unknown” (NULL in the database)?

is_extra_form() bool[source]

Is there an extra form from the researchers that they wish passed on to the patient?

mockup()[source]

Used to ensure test objects are OK.

notify_rdbm_of_bad_progress() None[source]

Lets the RDBM know that a clinician refused (vetoed) a request.

notify_rdbm_of_good_progress() None[source]

Lets the RDBM know that a clinician said yes to a request and wishes to do the work themselves.

notify_rdbm_of_work(letter: Letter, to_researcher: bool = False) None[source]

E-mail the RDBM to say that there’s work to do.

Parameters:
  • letter – a Letter

  • to_researcher – is it a letter that needs to go to a researcher manually, rather than a letter that a clinician wants the RDBM to send on their behalf?

process_request() None[source]

Processes the ContactRequest and marks it as processed. The main work is done by process_request_main().

process_request_main() None[source]

Act on a contact request and store the decisions made.

CORE DECISION-MAKING FUNCTION FOR THE CONSENT-TO-CONTACT PROCESS.

Writes to decisionlist.

request_by_address_components() List[str][source]

Returns the address of the person who made the contact request – or the Research Database Manager’s (with “c/o”) if we don’t know the requester’s.

This will be used in cases of a clinician-iniated request, for use in letters to the patient.

stop(msg: str) None[source]

Make a note of a decision and that we have finished processing this contact request, taking no further action.

store_clinician_details() None[source]

Ensure that if we have not got “override” details for the clinician, that we copy them from the patient lookup.

Withdraws consent that had previously been given. Will e-mail the researcher to let them know, if it can.

Returns:

letter, email_succeeded where letter is a Letter to the researcher and email_succeeded indicates whether we managed to e-mail the researcher.

Return type:

tuple

class crate_anon.crateweb.consent.models.Decision(*args, **kwargs)[source]

Abstract class to represent how a decision has been made (e.g. by a patient or their surrogate decision-maker or clinician).

decision_valid() bool[source]

Does the decision meet our rules about who can make decisions?

validate_decision() None[source]

Ensure that the decision is valid according to our rules, or raise django.forms.ValidationError.

class crate_anon.crateweb.consent.models.DummyObjectCollection(contact_request: ContactRequest, consent_mode: ConsentMode, patient_lookup: PatientLookup, study: Study, clinician_response: ClinicianResponse)[source]

A collection of dummy objects within the consent-to-contact system, for testing templates.

__init__(contact_request: ContactRequest, consent_mode: ConsentMode, patient_lookup: PatientLookup, study: Study, clinician_response: ClinicianResponse)[source]
class crate_anon.crateweb.consent.models.DummyPatientSourceInfo(*args, **kwargs)[source]

A patient lookup class that is a dummy one, for testing.

exception DoesNotExist
exception MultipleObjectsReturned
class crate_anon.crateweb.consent.models.Email(*args, **kwargs)[source]

Represents an e-mail sent (or to be sent) from CRATE.

exception DoesNotExist
exception MultipleObjectsReturned
classmethod create_clinician_email(contact_request: ContactRequest) Email[source]

Creates an e-mail to a clinician, asking them to consider a request from a study about a patient.

Parameters:

contact_request – a ContactRequest

Returns:

an Email

classmethod create_clinician_initiated_cr_email(contact_request: ContactRequest) Email[source]

Creates an e-mail to a clinician when they have initiated a contact request. This email will give them a link to the clinician pack if they said they’d contact the patient.

Parameters:

contact_request – a ContactRequest

Returns:

an Email

classmethod create_rdbm_email(subject: str, html: str) Email[source]

Create an HTML-based e-mail to the RDBM.

Parameters:
  • subject – subject line

  • html – HTML body

Returns:

an Email

classmethod create_rdbm_text_email(subject: str, text: str) Email[source]

Create an text-based e-mail to the RDBM.

Parameters:
  • subject – subject line

  • text – message body

Returns:

an Email

classmethod create_researcher_approval_email(contact_request: ContactRequest, letter: Letter) Email[source]

Creates an e-mail to a researcher, enclosing a letter giving them permission to contact a patient.

Parameters:
Returns:

an Email

classmethod create_researcher_withdrawal_email(contact_request: ContactRequest, letter: Letter) Email[source]

Creates an e-mail to a researcher, enclosing a letter withdrawing their permission to contact a patient.

Parameters:
Returns:

an Email

has_been_sent() bool[source]

Has this e-mail been sent?

(Internally: does an EmailTransmission for this e-mail exist with its sent flag set?)

resend(user: auth.User) None[source]

Resend this e-mail.

send(user: auth.User = None, resend: bool = False) EmailTransmission | None[source]

Sends the e-mail. Makes a record.

Parameters:
  • user – the sender.

  • resend – say that it’s OK to resend one that’s already been sent.

Returns:

an EmailTransmission object.

class crate_anon.crateweb.consent.models.EmailAttachment(*args, **kwargs)[source]

E-mail attachment class.

Typically, this does NOT manage its own files (i.e. if the attachment object is deleted, the files won’t be). Use this method for referencing files already stored elsewhere in the database.

If the owns_file attribute is set, however, the associated file is “owned” by this object, and the file will be deleted when the database object is.

exception DoesNotExist
exception MultipleObjectsReturned
classmethod create(email: Email, fileobj: FileField, content_type: str, sent_filename: str | None = None, owns_file=False) EmailAttachment[source]

Creates an e-mail attachment object and attaches it to an e-mail. When the e-mail is sent, the file thus referenced will be sent along with the e-mail; see Email.send().

Parameters:
  • email – an Email, to which this attachment is attached

  • fileobj – a django.db.models.FileField representing the file (on disk) to be attached

  • content_type – HTTP content type string

  • sent_filename – name of the filename as seen within the e-mail

  • owns_file – (see class help) Should the file on disk be deleted if/when this database object is deleted?

Returns:

a EmailAttachment

exists() bool[source]

Does the attached file exist on disk?

size() int[source]

Returns the size of the attachment in bytes, if it exists on disk (otherwise 0).

class crate_anon.crateweb.consent.models.EmailTransmission(*args, **kwargs)[source]

Represents an e-mail transmission attempt.

exception DoesNotExist
exception MultipleObjectsReturned
class crate_anon.crateweb.consent.models.Leaflet(*args, **kwargs)[source]

Represents a system-wide patient information leaflet.

exception DoesNotExist
exception MultipleObjectsReturned
static populate() None[source]

Pre-create records for all the system-wide leaflets we use.

class crate_anon.crateweb.consent.models.Letter(*args, **kwargs)[source]

Represents a letter (e.g. to a patient, clinician, or researcher).

exception DoesNotExist
exception MultipleObjectsReturned
classmethod create(basefilename: str, html: str | None = None, pdf: bytes | None = None, to_clinician: bool = False, to_researcher: bool = False, to_patient: bool = False, rdbm_may_view: bool = False, study: Study | None = None, contact_request: ContactRequest | None = None, debug_store_html: bool = False) Letter[source]

Creates a letter.

Parameters:
  • basefilename – filename to be used to store a PDF copy of the letter on disk (without a path)

  • html – for letters supplied as HTML, the HTML

  • pdf – for letters supplied as PDF, the PDF

  • to_clinician – is the letter to a clinician?

  • to_researcher – is the letter to a researcher?

  • to_patient – is the letter to a patient?

  • rdbm_may_view – may the RDBM view this letter?

  • study – which Study does it relate to, if any?

  • contact_request – which ContactRequest does it relate to, if any?

  • debug_store_html – should we store the HTML of the letter, as well as the PDF (for letters originating in HTML only)?

Returns:

a Letter

Creates a letter to a patient confirming their traffic-light consent-mode choice.

Parameters:

consent_mode – a ConsentMode

Returns:

a Letter

classmethod create_request_to_patient(contact_request: ContactRequest, rdbm_may_view: bool = False) Letter[source]

Creates a letter to a patient asking them about a specific study.

Parameters:
  • contact_request – a ContactRequest

  • rdbm_may_view – is this a request that the Research Database Manager (RDBM) is allowed to see under our information governance rules?

Returns:

a Letter

classmethod create_researcher_approval(contact_request: ContactRequest) Letter[source]

Creates a letter to a researcher giving approval to contact a patient.

Parameters:

contact_request – a ContactRequest

Returns:

a Letter

classmethod create_researcher_withdrawal(contact_request: ContactRequest) Letter[source]

Creates a letter to a researcher withdrawing previous approval to contact a patient.

Parameters:

contact_request – a ContactRequest

Returns:

a Letter

mark_sent() None[source]

Mark the letter as having been sent now.

class crate_anon.crateweb.consent.models.PatientLookup(*args, **kwargs)[source]

Represents a moment of lookup up identifiable data about patient, GP, and clinician from the relevant clinical database.

Inherits from PatientLookupBase so it has the same fields, and more.

exception DoesNotExist
exception MultipleObjectsReturned
get_first_traffic_light_letter_html() str[source]

Covering letter to patient for first enquiry about research preference.

Returns HTML for this document, customized to the patient.

set_from_clinician_info_holder(info: ClinicianInfoHolder) None[source]

Sets the clinician information fields from the supplied ClinicianInfoHolder.

class crate_anon.crateweb.consent.models.PatientLookupBase(*args, **kwargs)[source]

Base class for PatientLookup and DummyPatientSourceInfo.

Must be able to be instantiate with defaults, for the “not found” situation.

Note that derived classes must implement nhs_number as a column.

clinician_address_components() List[str][source]

Returns the clinician’s address – or the Research Database Manager’s (with “c/o”) if we don’t know the clinician’s.

(We’re going to put the clinician’s postal address into letters to patients. Therefore, we need a sensible fallback, i.e. the RDBM’s.)

clinician_address_components_str() str[source]

Returns the clinician’s address in single-line format.

clinician_name_address_str() str[source]

Returns the clinician’s name and address in single-line format.

clinician_salutation() str[source]

Returns the salutation for the patient’s clinician (e.g. “Dr Paroxetine”).

clinician_title_forename_surname() str[source]

Returns the title/forename/surname for the patient’s clinician (e.g. “Dr Petra Paroxetine”).

days_since_discharge() int | None[source]

Returns the number of days since discharge, or None if the patient is not discharged (or if we don’t know).

get_id_numbers_as_str() str[source]

Returns ID numbers, in a format like “NHS#: 123. RiO# 456.”

get_pt_age_years() int | None[source]

Returns the patient’s current age in years, or None if unknown.

get_traffic_light_decision_form(generic: bool = False) str[source]

Returns HTML for a traffic-light decision form, customized to this patient.

gp_address_components() List[str][source]

Returns address lines for the GP (e.g. for an envelope).

gp_address_components_str() str[source]

Returns the GP’s address as a single line.

gp_name_address_str() str[source]

Returns the GP’s name and address as a single line.

gp_title_forename_surname() str[source]

Returns the title/forename/surname for the patient’s GP, like “Dr Joe Bloggs”.

is_under_15() bool[source]

Is the patient under 15?

is_under_16() bool[source]

Is the patient under 16?

pt_address_components() List[str][source]

Returns lines of the patient’s address (e.g. for letter headings or envelopes).

pt_address_components_str() str[source]

Returns the patient’s address as a single (one-line) string.

pt_forename_surname() str[source]

Returns the patient’s forename/surname, like “Ann Smith”.

pt_name_address_components() List[str][source]

Returns the patient’s name and address, as lines (e.g. for an envelope).

pt_salutation() str[source]

Returns a salutation for the patient, like “Mrs Smith”.

pt_title_forename_surname() str[source]

Returns the patient’s title/forename/surname, like “Mrs Ann Smith”.

set_gp_name_components(name: str, decisions: List[str], secret_decisions: List[str]) None[source]

Takes a name, splits it into components as best it can, and stores it in the gp_title, gp_first_name, and gp_last_name fields.

Parameters:
  • name – GP name, e.g. “Dr Joe Bloggs”

  • decisions – list of human-readable decisions; will be modified

  • secret_decisions – list of human-readable decisions containing secret (identifiable) information; will be modified

class crate_anon.crateweb.consent.models.PatientResponse(*args, **kwargs)[source]

Represents the patient’s decision about a specific study. (We get one of these if the clinician passed details to the patient and the patient has responded.)

exception DoesNotExist
exception MultipleObjectsReturned
classmethod create(contact_request: ContactRequest) PatientResponse[source]

Creates a patient response object for a given contact request.

Parameters:

contact_request – a ContactRequest

Returns:

PatientResponse

static get_unprocessed() QuerySet[source]

Return all PatientResponse objects that need processing.

See crate_anon.crateweb.consent.tasks.process_patient_response() and process_response(), which does the work.

process_response() None[source]

Processes the PatientResponse and marks it as processed.

If the patient said yes, this triggers a letter to the researcher.

class crate_anon.crateweb.consent.models.Study(*args, **kwargs)[source]

Represents a research study.

exception DoesNotExist
exception MultipleObjectsReturned
static filter_studies_for_researcher(queryset: QuerySet, user: auth.User) QuerySet[source]

Filters the supplied query set down to those studies for which the given user is a researcher on.

get_involves_lack_of_capacity() str[source]

Returns a human-readable string indicating whether or not the study involves patients lacking capacity (and if so, whether it’s a clinical trial [CTIMP]).

get_lead_researcher_name_address() List[str][source]

Returns name/address components (as lines you might use on a letter or envelope) for the study’s lead researcher.

get_lead_researcher_salutation() str[source]

Returns the salutation for the study’s lead researcher (e.g. “Prof. Jones”).

static get_queryset_possible_contact_studies() QuerySet[source]

Returns all approved studies involving direct patient contact that have a properly identifiable lead researcher.

property html_summary: str

Returns a version of the study’s summary with HTML tags marking up paragraphs. If the summary is already in HTML format, just return that.

class crate_anon.crateweb.consent.models.TeamInfo[source]

Represents information about all clinical teams, fetched from a clinical source database.

Provides some simple views on crate_anon.crateweb.consent.teamlookup.get_teams().

classmethod team_choices() List[Tuple[str, str]][source]

Returns a Django choice list, i.e. a list of tuples like value, description.

static teams() List[str][source]

Returns all clinical team names.

class crate_anon.crateweb.consent.models.TeamRep(*args, **kwargs)[source]

Represents a clinical team representative, which is recorded in CRATE.

exception DoesNotExist
exception MultipleObjectsReturned
crate_anon.crateweb.consent.models.auto_delete_emailattachment_files_on_change(sender: Type[EmailAttachment], instance: EmailAttachment, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when EmailAttachment object is changed, if its owns_file flag is set.

crate_anon.crateweb.consent.models.auto_delete_emailattachment_files_on_delete(sender: Type[EmailAttachment], instance: EmailAttachment, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when EmailAttachment object is deleted, if its owns_file flag is set.

crate_anon.crateweb.consent.models.auto_delete_leaflet_files_on_change(sender: Type[Leaflet], instance: Leaflet, **kwargs: Any) None[source]

Django signal receiver. Deletes files from filesystem when Leaflet object is changed.

crate_anon.crateweb.consent.models.auto_delete_leaflet_files_on_delete(sender: Type[Leaflet], instance: Leaflet, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when Leaflet object is deleted.

crate_anon.crateweb.consent.models.auto_delete_letter_files_on_change(sender: Type[Letter], instance: Letter, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when a Letter object is changed.

crate_anon.crateweb.consent.models.auto_delete_letter_files_on_delete(sender: Type[Letter], instance: Letter, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when a Letter object is deleted.

crate_anon.crateweb.consent.models.auto_delete_study_files_on_change(sender: Type[Study], instance: Study, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when Study object is changed.

crate_anon.crateweb.consent.models.auto_delete_study_files_on_delete(sender: Type[Study], instance: Study, **kwargs: Any) None[source]

Django signal receiver.

Deletes files from filesystem when Study object is deleted.

crate_anon.crateweb.consent.models.leaflet_upload_to(instance: Leaflet, filename: str) str[source]

Determines the filename used for leaflet uploads.

Parameters:
  • instance – instance of Leaflet (potentially unsaved; and you can’t call save(); it goes into infinite recursion)

  • filename – uploaded filename

Returns:

filename with extension but without path, to be used on the server filesystem

crate_anon.crateweb.consent.models.make_dummy_objects(request: HttpRequest, test_id: str = '-1') DummyObjectCollection[source]

Returns a collection of dummy objects, for testing consent-to-contact templates without using live patient data.

Parameters:

request – the django.http.request.HttpRequest

Returns:

a DummyObjectCollection

We want to create these objects in memory, without saving to the DB. However, Django is less good at SQLAlchemy for this, and saves.

A simple method works for an SQLite backend database but fails with an IntegrityError for MySQL/SQL Server. For example:

IntegrityError at /draft_traffic_light_decision_form/-1/html/
(1452, 'Cannot add or update a child row: a foreign key constraint
fails (`crate_django`.`consent_study_researchers`, CONSTRAINT
`consent_study_researchers_study_id_19bb255f_fk_consent_study_id`
FOREIGN KEY (`study_id`) REFERENCES `consent_study` (`id`))')

This occurs in the first creation, of a Study, and only if you specify researchers.

The reason for the crash is that researchers is a ManyToManyField, and Django is trying to set the user.studies_as_researcher back-reference, but can’t do so because the Study doesn’t have a PK yet.

Since this is a minor thing, and templates are unaffected, and this is only for debugging, let’s ignore it.

crate_anon.crateweb.consent.models.study_details_upload_to(instance: Study, filename: str) str[source]

Determines the filename used for study information PDF uploads.

Parameters:
  • instance – instance of Study (potentially unsaved; and you can’t call save(); it goes into infinite recursion)

  • filename – uploaded filename

Returns:

filename with extension but without path, to be used on the server filesystem

crate_anon.crateweb.consent.models.study_form_upload_to(instance: Study, filename: str) str[source]

Determines the filename used for study clinician-form PDF uploads.

Parameters:
  • instance – instance of Study (potentially unsaved and you can’t call save(); it goes into infinite recursion)

  • filename – uploaded filename

Returns:

filename with extension but without path, to be used on the server filesystem