Base models, forms and admin for participant ICF for clinicedc/edc projects
Project description
edc-consent
Add classes for the Informed Consent form and process.
Installation
Register your consent model, its version and period of validity, with site_consents. site_consents will autodiscover consents.py in any app listed in INSTALLED_APPS. For now we just create a version 1 consent. In consents.py add something like this:
from datetime import datetime
from zoneifo import ZoneInfo
from edc_consent.consent_definition import ConsentDefinition
from edc_consent.site_consents import site_consents
from edc_constants.constants import MALE, FEMALE
subjectconsent_v1 = ConsentDefinition(
'edc_example.subjectconsent',
version='1',
start=datetime(2013, 10, 15, tzinfo=ZoneInfo("UTC")),
end=datetime(2016, 10, 15, tzinfo=ZoneInfo("UTC")),
age_min=16,
age_is_adult=18,
age_max=64,
gender=[MALE, FEMALE])
site_consents.register(subjectconsent_v1)
add to settings:
INSTALLED_APPS = [
...
'edc_consent.apps.AppConfig',
...
]
Below needs to be updated
Features
base class for an informed consent document
data for models that require consent cannot be add until the consent is added
consents have a version number and validity period
maximum number of consented subjects can be controlled.
data collection is only allowed within the validity period of the consent per consented participant
data for models that require consent are tagged with the consent version
TODO
link subject type to the consent model. e.g. maternal, infant, adult, etc.
version at model field level (e.g. a new consent period adds additional questions to a form)
allow a different subject’s consent to cover for another, for example mother and infant.
Usage
Then declare the consent model:
class SubjectConsent(
ConsentModelMixin,
SiteModelMixin,
UpdatesOrCreatesRegistrationModelMixin,
NonUniqueSubjectIdentifierModelMixin,
IdentityFieldsMixin,
PersonalFieldsMixin,
SampleCollectionFieldsMixin,
ReviewFieldsMixin,
VulnerabilityFieldsMixin,
SearchSlugModelMixin,
BaseUuidModel,
):
"""A model completed by the user that captures the ICF."""
subject_identifier_cls = SubjectIdentifier
subject_screening_model = "effect_screening.subjectscreening"
objects = SubjectConsentManager()
on_site = CurrentSiteManager()
consent = ConsentManager()
history = HistoricalRecords()
class Meta(ConsentModelMixin.Meta, BaseUuidModel.Meta):
pass
Declare the ModelForm:
class MyConsentForm(BaseConsentForm):
class Meta:
model = MyConsent
Now that you have a consent model class, identify and declare the models that will require this consent:
class Questionnaire(RequiresConsentMixin, models.Model):
consent_model = MyConsent # or tuple (app_label, model_name)
report_datetime = models.DateTimeField(default=timezone.now)
question1 = models.CharField(max_length=10)
question2 = models.CharField(max_length=10)
question3 = models.CharField(max_length=10)
@property
def subject_identifier(self):
"""Returns the subject identifier from ..."""
return subject_identifier
class Meta:
app_label = 'my_app'
verbose_name = 'My Questionnaire'
Notice above the first two class attributes, namely:
consent_model: this is the consent model class that was declared above;
report_datetime: a required field used to lookup the correct consent version from ConsentType and to find, together with subject_identifier, a valid instance of MyConsent;
Also note the property subject_identifier.
subject_identifier: a required property that knows how to find the subject_identifier for the instance of Questionnaire.
Once all is declared you need to:
define the consent version and validity period for the consent version in ConsentType;
add a Quota for the consent model.
As subjects are identified:
add a consent
add the models (e.g. Questionnaire)
If a consent version cannot be found given the consent model class and report_datetime a ConsentTypeError is raised.
If a consent for this subject_identifier cannot be found that matches the ConsentType a NotConsentedError is raised.
Specimen Consent
A participant may consent to the study but not agree to have specimens stored long term. A specimen consent is administered separately to clarify the participant's intention.
The specimen consent is declared using the base class BaseSpecimenConsent. This is an abridged version of BaseConsent. The specimen consent also uses the RequiresConsentMixin as it cannot stand alone as an ICF. The RequiresConsentMixin ensures the specimen consent is administered after the main study ICF, in this case MyStudyConsent.
A specimen consent is declared in your app like this:
class SpecimenConsent(
BaseSpecimenConsent, SampleCollectionFieldsMixin, RequiresConsentMixin,
VulnerabilityFieldsMixin, AppointmentMixin, BaseUuidModel
):
consent_model = MyStudyConsent
registered_subject = models.OneToOneField(RegisteredSubject, null=True)
objects = models.Manager()
history = AuditTrail()
class Meta:
app_label = 'my_app'
verbose_name = 'Specimen Consent'
Validators
The ConsentAgeValidator validates the date of birth to within a given age range, for example:
from edc_consent.validtors import ConsentAgeValidator
class MyConsent(ConsentQuotaMixin, BaseConsent):
dob = models.DateField(
validators=[ConsentAgeValidator(16, 64)])
quota = QuotaManager()
class Meta:
app_label = 'my_app'
The PersonalFieldsMixin includes a date of birth field and you can set the age bounds like this:
from edc_consent.validtors import ConsentAgeValidator
from edc_consent.models.fields import PersonalFieldsMixin
class MyConsent(ConsentQuotaMixin, PersonalFieldsMixin, BaseConsent):
quota = QuotaManager()
MIN_AGE_OF_CONSENT = 18
MAX_AGE_OF_CONSENT = 64
class Meta:
app_label = 'my_app'
Common senarios
Tracking the consent version with collected data
All model data is tagged with the consent version identified in ConsentType for the consent model class and report_datetime.
Reconsenting consented subjects when the consent changes
The consent model is unique on subject_identifier, identity and version. If a new consent version is added to ConsentType, a new consent will be required for each subject as data is reported within the validity period of the new consent.
Some care must be taken to ensure that the consent model is queried with an understanding of the unique constraint.
Linking the consent version to added or removed model fields on models that require consent
TODO
Infants use mother’s consent
TODO
By adding the property consenting_subject_identifier to the consent
Patient names
If patient names need to be removed from the data collection, there are a few helper attributes and methods to consider.
settings.EDC_CONSENT_REMOVE_PATIENT_NAMES_FROM_COUNTRIES: list[str]
If given a list of country names, name fields will be removed from any admin.fieldset.
See also edc_sites.all_sites
ConsentModelAdminMixin.get_fieldsets
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
for country in get_remove_patient_names_from_countries():
site = getattr(request, "site", None)
if site and site.id in [s.site_id for s in self.all_sites.get(country)]:
return self.fieldsets_without_names(fieldsets)
return fieldsets
This method could be added to any ModeLadmin with names.
using
Other TODO
Timepoint model update in save method of models requiring consent
handle added or removed model fields (questions) because of consent version change
review verification actions
management command to update version on models that require consent (if edc_consent added after instances were created)
handle re-consenting issues, for example, if original consent was restricted by age (16-64) but the re-consent is not. May need to open upper bound.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file edc-consent-0.3.70.tar.gz
.
File metadata
- Download URL: edc-consent-0.3.70.tar.gz
- Upload date:
- Size: 64.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 053445ac07eb16d3f61d778b8022d6e5bde1570b13edb833054dd95571ce5b32 |
|
MD5 | 43f9d07edf7fcbd97404ac9239c6df78 |
|
BLAKE2b-256 | c26746d90039cff68eb0037a4892c54e684410c2ede235fe23eeb79cc414a926 |
File details
Details for the file edc_consent-0.3.70-py3-none-any.whl
.
File metadata
- Download URL: edc_consent-0.3.70-py3-none-any.whl
- Upload date:
- Size: 78.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3f610da6722ec2653fd9e335a8d73a8feb4a9eb2d0d5ac1501bf3fc9f2056b16 |
|
MD5 | 78393e9106844be72b451618419c4722 |
|
BLAKE2b-256 | 3b641666eac31805631c944b8ec708f360f7662ddac0ec6415ff07331a49f72e |