signoffs.core.forms#

Forms for collecting and revoking signoffs.

Challenges:

  • the Signet form itself is just a labelled checkbox - it doesn’t display any model fields. Yet, it should behave like a model form, defining a signoff instance once validated.

  • the form is only displayed when there is no instance - you can’t edit a saved signoff, only revoke it. So these forms don’t have an instance - they are only used to “add” a signoff.

  • the form itself likely needs an association to the Signoff Type so it can be rendered correctly.

  • so, the signoff type itself might be obtained from the request data (e.g., in a generic view) So if the request is bad, it may not be possible to construct a Form class to validate rest of data.

Signets with relations: The form is being used to sign off on something specific, so it likely needs a relation to some concrete object. So the view will need some way to know which object is being signed off on.

To solve this for concrete Signets with relational fields, try ONE of these approaches:

  • pre-create the signoff instance, with relations in place, and pass it to the form. The Signet instance, with its relations, will be saved if form validates and is signed.

  • specialize AbstractSignoffForm to add hidden fields with the extra relation data; Use initial data to populate these fields and be sure to override clean() to validate the extra data.

Module Contents#

Classes#

AbstractSignoffForm

Abstract Base class for the signoff_form_factory

AbstractSignoffRevokeForm

Form used to validate requests to revoke a signoff - not really intended to be user-facing. Not intended to collect signoffs, but rather simply to house the validation logic for revoke requests, which may be delete rather than post requests. It is not a ModelForm so it remains as generic as possible, though in many ways a Signet ModelForm might be useful.

SignoffTypeForms

Manage the forms used by a particular signoff type - usually injected using a FormsManager service

SignoffFormsManager

A descriptor class that “injects” a SignoffTypeForms instance into a Signoff instance.

Functions#

signoff_form_factory

Returns a Form class suited to collecting a signoff. Not unlike modelform_factory, except the model is provided by the signoff_type. baseForm can be overridden to add additional fields and/or fully customize validation and save logic. Validation ensures the type of signoff in POST matches the type provided. Signing this form with a User performs a permissions check and saves the signoff, if required.

revoke_form_factory

Returns a Form class suited to validation a signoff revoke request. Not unlike modelform_factory, except the model is provided by the signoff_type. baseForm can be overridden to add additional fields and/or fully customize validation and save logic. Validation ensures the type of signoff in POST matches the type provided. Revoking this form with a User performs a permissions check and deletes the signoff’s signet, if required.

API#

class signoffs.core.forms.AbstractSignoffForm(*args, instance=None, **kwargs)[source]#

Bases: django.forms.ModelForm

Abstract Base class for the signoff_form_factory

Initialization

Form accepts an optional signoff, used like the instance parameter for ModelForms to pass initial values. Form also accepts ‘user’ as optional kwarg: the user who is signing off

signed_off#

None

signoff_id#

None

class Meta[source]#
model#

None

exclude#

[‘user’, ‘sigil’, ‘sigil_label’, ‘timestamp’]

is_signed_off()[source]#

return True iff this form is signed off

clean()[source]#

Validate signoff for consistency with the instance form was intialized with.

Note

Don’t be tempted to check permissions here! The form is clean even if user doesn’t have permission!

sign(user, commit=True)[source]#

Sign and save this form for the given user, without checking permissions (no business logic invoked!)

Returns:

the saved Signet instance, or None if the signoff was not actually signed.

Note

If signoff has m2m relations and commit==False, caller is responsible to call self.save_m2m()

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

Disable normal form save() method - signoff forms must be signed by a user

signoffs.core.forms.signoff_form_factory(signoff_type, baseForm=AbstractSignoffForm, form_prefix=None, signoff_field_kwargs=None)[source]#

Returns a Form class suited to collecting a signoff. Not unlike modelform_factory, except the model is provided by the signoff_type. baseForm can be overridden to add additional fields and/or fully customize validation and save logic. Validation ensures the type of signoff in POST matches the type provided. Signing this form with a User performs a permissions check and saves the signoff, if required.

class signoffs.core.forms.AbstractSignoffRevokeForm(*args, **kwargs)[source]#

Bases: django.forms.Form

Form used to validate requests to revoke a signoff - not really intended to be user-facing. Not intended to collect signoffs, but rather simply to house the validation logic for revoke requests, which may be delete rather than post requests. It is not a ModelForm so it remains as generic as possible, though in many ways a Signet ModelForm might be useful.

Initialization

Form requires the signetModel class of the signet to be revoked

signoff_id#

None

signet_pk#

None

_get_signoff_type()[source]#
_get_signet(signoff_type)[source]#
clean()[source]#

Validate the signoff type for the form’s signet matches the form’s signoff type

Note

Don’t be tempted to check permissions here! The form is clean even if user doesn’t have permission!

revoke(user, commit=True)[source]#

Revoke the signoff validated by this form, and return the revoked signoff, without checking permissions (no business logic invoked!)

If commit is False, the form is validated and the signoff to be revoked is returned - up to you to revoke it.

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

Disable normal form save() method - signoff forms must be signed by a user

signoffs.core.forms.revoke_form_factory(signoff_type, baseForm=AbstractSignoffRevokeForm, form_prefix=None, signoff_field_kwargs=None)[source]#

Returns a Form class suited to validation a signoff revoke request. Not unlike modelform_factory, except the model is provided by the signoff_type. baseForm can be overridden to add additional fields and/or fully customize validation and save logic. Validation ensures the type of signoff in POST matches the type provided. Revoking this form with a User performs a permissions check and deletes the signoff’s signet, if required.

class signoffs.core.forms.SignoffTypeForms(signoff_type, signoff_form=None, revoke_form=None)[source]#

Manage the forms used by a particular signoff type - usually injected using a FormsManager service

Initialization

signoff_form: signoffs.core.forms.opt_callable#

None

baseForm type passed to signoff_form_factory or a callable that returns a Form subclass

revoke_form: signoffs.core.forms.opt_callable#

None

baseForm type passed to revoke_form_factory or a callable that returns a Form subclass

static _get_form_class(candidate)[source]#

candidate may be a Form subclass or a callable that returns one - return the Form subclass either way

get_signoff_form_class(**kwargs)[source]#

Return a form class suitable for collecting a signoff of this Type. kwargs passed through to factory.

get_revoke_form_class(**kwargs)[source]#

Return a form class suitable for validating revoke request for a signoff of this Type.

get_signoff_form(data=None, **kwargs)[source]#

Return a form instance suited to collecting this signoff type for simple case, no factory args required

get_revoke_form(data=None, **kwargs)[source]#

Return a form instance suited to revoking this signoff type for simple case, no factory args required

class signoffs.core.forms.SignoffFormsManager[source]#

Bases: class_service(service_class=SignoffTypeForms)

A descriptor class that “injects” a SignoffTypeForms instance into a Signoff instance.

To inject custom form services:

  • provide a custom service_class: forms=SignoffFormsManager(service_class=MyInstanceForms)

  • OR specialize class attributes: MySignoffFormsManager = utils.service(SignoffTypeForms, signoff_form=mySignoffForm)

  • OR both… MySignoffFormsManager = utils.service(MyInstanceForms)

signoffs.contrib.approvals.forms#

A form for collecting approval signoffs

Module Contents#

Classes#

ApprovalSignoffForm

Form for collecting approval signoffs

API#

class signoffs.contrib.approvals.forms.ApprovalSignoffForm(*args, instance=None, **kwargs)[source]#

Bases: signoffs.core.forms.AbstractSignoffForm

Form for collecting approval signoffs

Initialization

Form accepts an optional signoff, used like the instance parameter for ModelForms to pass initial values. Form also accepts ‘user’ as optional kwarg: the user who is signing off

class Meta[source]#

Bases: signoffs.core.forms.AbstractSignoffForm.Meta

model#

None

widgets#

None