Package: edc-consent
edc-consentAdd classes for the Informed Consent form and process.InstallationRegister your consent model, its version and period of validity, withsite_consents.site_consentswillautodiscoverconsents.pyin any app listed inINSTALLED_APPS. For now we just create a version 1 consent. Inconsents.pyadd something like this:fromdatetimeimportdatetimefromzoneifoimportZoneInfofromedc_consent.consent_definitionimportConsentDefinitionfromedc_consent.site_consentsimportsite_consentsfromedc_constants.constantsimportMALE,FEMALEsubjectconsent_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',...]BelowneedstobeupdatedFeaturesbase class for an informed consent documentdata for models that require consent cannot be add until the consent is addedconsents have a version number and validity periodmaximum number of consented subjects can be controlled.data collection is only allowed within the validity period of the consent per consented participantdata for models that require consent are tagged with the consent versionTODOlink 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.UsageThen declare the consent model:classSubjectConsent(ConsentModelMixin,SiteModelMixin,UpdatesOrCreatesRegistrationModelMixin,NonUniqueSubjectIdentifierModelMixin,IdentityFieldsMixin,PersonalFieldsMixin,SampleCollectionFieldsMixin,ReviewFieldsMixin,VulnerabilityFieldsMixin,SearchSlugModelMixin,BaseUuidModel,):"""A model completed by the user that captures the ICF."""subject_identifier_cls=SubjectIdentifiersubject_screening_model="effect_screening.subjectscreening"objects=SubjectConsentManager()on_site=CurrentSiteManager()consent=ConsentManager()history=HistoricalRecords()classMeta(ConsentModelMixin.Meta,BaseUuidModel.Meta):passDeclare the ModelForm:classMyConsentForm(BaseConsentForm):classMeta:model=MyConsentNow that you have a consent model class, identify and declare the models that will require this consent:classQuestionnaire(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)@propertydefsubject_identifier(self):"""Returns the subject identifier from ..."""returnsubject_identifierclassMeta: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 withsubject_identifier,  a valid instance ofMyConsent;Also note the propertysubject_identifier.subject_identifier: a required property that knows how to find thesubject_identifierfor the instance ofQuestionnaire.Once all is declared you need to:define the consent version and validity period for the consent version inConsentType;add a Quota for the consent model.As subjects are identified:add a consentadd the models (e.g.Questionnaire)If a consent version cannot be found given the consent model class and report_datetime aConsentTypeErroris raised.If a consent for this subject_identifier cannot be found that matches theConsentTypeaNotConsentedErroris raised.Specimen ConsentA 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 classBaseSpecimenConsent. This is an abridged version ofBaseConsent. The specimen consent also uses theRequiresConsentMixinas it cannot stand alone as an ICF. TheRequiresConsentMixinensures the specimen consent is administered after the main study ICF, in this caseMyStudyConsent.A specimen consent is declared in your app like this:classSpecimenConsent(BaseSpecimenConsent,SampleCollectionFieldsMixin,RequiresConsentMixin,VulnerabilityFieldsMixin,AppointmentMixin,BaseUuidModel):consent_model=MyStudyConsentregistered_subject=models.OneToOneField(RegisteredSubject,null=True)objects=models.Manager()history=AuditTrail()classMeta:app_label='my_app'verbose_name='Specimen Consent'ValidatorsTheConsentAgeValidatorvalidates the date of birth to within a given age range, for example:fromedc_consent.validtorsimportConsentAgeValidatorclassMyConsent(ConsentQuotaMixin,BaseConsent):dob=models.DateField(validators=[ConsentAgeValidator(16,64)])quota=QuotaManager()classMeta:app_label='my_app'ThePersonalFieldsMixinincludes a date of birth field and you can set the age bounds like this:fromedc_consent.validtorsimportConsentAgeValidatorfromedc_consent.models.fieldsimportPersonalFieldsMixinclassMyConsent(ConsentQuotaMixin,PersonalFieldsMixin,BaseConsent):quota=QuotaManager()MIN_AGE_OF_CONSENT=18MAX_AGE_OF_CONSENT=64classMeta:app_label='my_app'Common senariosTracking the consent version with collected dataAll model data is tagged with the consent version identified inConsentTypefor the consent model class and report_datetime.Reconsenting consented subjects when the consent changesThe consent model is unique on subject_identifier, identity and version. If a new consent version is added toConsentType, 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 consentTODOInfants use mother’s consentTODOBy adding the propertyconsenting_subject_identifierto the consentPatient namesIf 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_sitesConsentModelAdminMixin.get_fieldsetsdefget_fieldsets(self,request,obj=None):fieldsets=super().get_fieldsets(request,obj)forcountryinget_remove_patient_names_from_countries():site=getattr(request,"site",None)ifsiteandsite.idin[s.site_idforsinself.all_sites.get(country)]:returnself.fieldsets_without_names(fieldsets)returnfieldsetsThis method could be added to any ModeLadmin with names.usingOther TODOTimepointmodel update insavemethod of models requiring consenthandle added or removed model fields (questions) because of consent version changereview verification actionsmanagement 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.