mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-06-09 14:04:44 +02:00
Merge branch 'main' into nmb/federal-combobox
This commit is contained in:
commit
5d56c88ba5
21 changed files with 1021 additions and 319 deletions
|
@ -8,63 +8,53 @@ from typing import Union
|
|||
|
||||
from django import forms
|
||||
from django.shortcuts import render
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import resolve
|
||||
|
||||
from formtools.wizard.views import NamedUrlSessionWizardView # type: ignore
|
||||
|
||||
from registrar.models import DomainApplication, Domain
|
||||
from registrar.models import Contact, DomainApplication, Domain
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Subclass used to remove the default colon suffix from all fields
|
||||
class RegistrarForm(forms.Form):
|
||||
"""Subclass used to remove the default colon suffix from all fields."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("label_suffix", "")
|
||||
super(RegistrarForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def to_database(self, obj: DomainApplication | Contact):
|
||||
"""
|
||||
Adds this form's cleaned data to `obj` and saves `obj`.
|
||||
|
||||
Does nothing if form is not valid.
|
||||
"""
|
||||
if not self.is_valid():
|
||||
return
|
||||
for name, value in self.cleaned_data.items():
|
||||
setattr(obj, name, value)
|
||||
obj.save()
|
||||
|
||||
def from_database(self, obj: DomainApplication | Contact):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
for name in self.declared_fields.keys():
|
||||
self.initial[name] = getattr(obj, name) # type: ignore
|
||||
|
||||
|
||||
class OrganizationTypeForm(RegistrarForm):
|
||||
organization_type = forms.ChoiceField(
|
||||
required=True,
|
||||
choices=[
|
||||
(DomainApplication.FEDERAL, "Federal: a federal agency"),
|
||||
(
|
||||
DomainApplication.INTERSTATE,
|
||||
"Interstate: an organization of two or more states",
|
||||
),
|
||||
(
|
||||
DomainApplication.STATE_OR_TERRITORY,
|
||||
(
|
||||
"State or Territory: One of the 50 U.S. states, the District of "
|
||||
"Columbia, American Samoa, Guam, Northern Mariana Islands, "
|
||||
"Puerto Rico, or the U.S. Virgin Islands"
|
||||
),
|
||||
),
|
||||
(
|
||||
DomainApplication.TRIBAL,
|
||||
(
|
||||
"Tribal: a tribal government recognized by the federal or "
|
||||
"state government"
|
||||
),
|
||||
),
|
||||
(DomainApplication.COUNTY, "County: a county, parish, or borough"),
|
||||
(DomainApplication.CITY, "City: a city, town, township, village, etc."),
|
||||
(
|
||||
DomainApplication.SPECIAL_DISTRICT,
|
||||
"Special District: an independent organization within a single state",
|
||||
),
|
||||
],
|
||||
choices=DomainApplication.OrganizationChoices.choices,
|
||||
widget=forms.RadioSelect,
|
||||
)
|
||||
|
||||
|
||||
class OrganizationFederalForm(RegistrarForm):
|
||||
federal_type = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=DomainApplication.BRANCH_CHOICES,
|
||||
choices=DomainApplication.BranchChoices.choices,
|
||||
widget=forms.RadioSelect,
|
||||
)
|
||||
|
||||
|
@ -77,7 +67,6 @@ class OrganizationElectionForm(RegistrarForm):
|
|||
(False, "No"),
|
||||
],
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
|
||||
|
||||
|
@ -236,71 +225,32 @@ class OrganizationContactForm(RegistrarForm):
|
|||
required=False,
|
||||
label="Address line 2",
|
||||
)
|
||||
us_state = forms.ChoiceField(
|
||||
label="State",
|
||||
choices=[
|
||||
("AL", "Alabama"),
|
||||
("AK", "Alaska"),
|
||||
("AZ", "Arizona"),
|
||||
("AR", "Arkansas"),
|
||||
("CA", "California"),
|
||||
("CO", "Colorado"),
|
||||
("CT", "Connecticut"),
|
||||
("DE", "Delaware"),
|
||||
("DC", "District of Columbia"),
|
||||
("FL", "Florida"),
|
||||
("GA", "Georgia"),
|
||||
("HI", "Hawaii"),
|
||||
("ID", "Idaho"),
|
||||
("IL", "Illinois"),
|
||||
("IN", "Indiana"),
|
||||
("IA", "Iowa"),
|
||||
("KS", "Kansas"),
|
||||
("KY", "Kentucky"),
|
||||
("LA", "Louisiana"),
|
||||
("ME", "Maine"),
|
||||
("MD", "Maryland"),
|
||||
("MA", "Massachusetts"),
|
||||
("MI", "Michigan"),
|
||||
("MN", "Minnesota"),
|
||||
("MS", "Mississippi"),
|
||||
("MO", "Missouri"),
|
||||
("MT", "Montana"),
|
||||
("NE", "Nebraska"),
|
||||
("NV", "Nevada"),
|
||||
("NH", "New Hampshire"),
|
||||
("NJ", "New Jersey"),
|
||||
("NM", "New Mexico"),
|
||||
("NY", "New York"),
|
||||
("NC", "North Carolina"),
|
||||
("ND", "North Dakota"),
|
||||
("OH", "Ohio"),
|
||||
("OK", "Oklahoma"),
|
||||
("OR", "Oregon"),
|
||||
("PA", "Pennsylvania"),
|
||||
("RI", "Rhode Island"),
|
||||
("SC", "South Carolina"),
|
||||
("SD", "South Dakota"),
|
||||
("TN", "Tennessee"),
|
||||
("TX", "Texas"),
|
||||
("UT", "Utah"),
|
||||
("VT", "Vermont"),
|
||||
("VA", "Virginia"),
|
||||
("WA", "Washington"),
|
||||
("WV", "West Virginia"),
|
||||
("WI", "Wisconsin"),
|
||||
("WY", "Wyoming"),
|
||||
("AS", "American Samoa"),
|
||||
("GU", "Guam"),
|
||||
("MP", "Northern Mariana Islands"),
|
||||
("PR", "Puerto Rico"),
|
||||
("VI", "Virgin Islands"),
|
||||
],
|
||||
state_territory = forms.ChoiceField(
|
||||
label="State", choices=DomainApplication.StateTerritoryChoices.choices
|
||||
)
|
||||
zipcode = forms.CharField(label="ZIP code")
|
||||
|
||||
|
||||
class AuthorizingOfficialForm(RegistrarForm):
|
||||
def to_database(self, obj):
|
||||
"""Adds this form's cleaned data to `obj` and saves `obj`."""
|
||||
if not self.is_valid():
|
||||
return
|
||||
contact = getattr(obj, "authorizing_official", None)
|
||||
if contact is not None:
|
||||
super().to_database(contact)
|
||||
else:
|
||||
contact = Contact()
|
||||
super().to_database(contact)
|
||||
obj.authorizing_official = contact
|
||||
obj.save()
|
||||
|
||||
def from_database(self, obj):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
contact = getattr(obj, "authorizing_official", None)
|
||||
if contact is not None:
|
||||
super().from_database(contact)
|
||||
|
||||
first_name = forms.CharField(label="First name/given name")
|
||||
middle_name = forms.CharField(
|
||||
required=False,
|
||||
|
@ -313,6 +263,22 @@ class AuthorizingOfficialForm(RegistrarForm):
|
|||
|
||||
|
||||
class CurrentSitesForm(RegistrarForm):
|
||||
def to_database(self, obj):
|
||||
"""Adds this form's cleaned data to `obj` and saves `obj`."""
|
||||
if not self.is_valid():
|
||||
return
|
||||
obj.save()
|
||||
normalized = Domain.normalize(self.cleaned_data["current_site"], blank=True)
|
||||
if normalized:
|
||||
# TODO: ability to update existing records
|
||||
obj.current_websites.create(website=normalized)
|
||||
|
||||
def from_database(self, obj):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
current_website = obj.current_websites.first()
|
||||
if current_website is not None:
|
||||
self.initial["current_site"] = current_website.website
|
||||
|
||||
current_site = forms.CharField(
|
||||
required=False,
|
||||
label="Enter your organization’s public website, if you have one. For example, "
|
||||
|
@ -321,7 +287,42 @@ class CurrentSitesForm(RegistrarForm):
|
|||
|
||||
|
||||
class DotGovDomainForm(RegistrarForm):
|
||||
dotgov_domain = forms.CharField(label="What .gov domain do you want?")
|
||||
def to_database(self, obj):
|
||||
"""Adds this form's cleaned data to `obj` and saves `obj`."""
|
||||
if not self.is_valid():
|
||||
return
|
||||
normalized = Domain.normalize(
|
||||
self.cleaned_data["requested_domain"], "gov", blank=True
|
||||
)
|
||||
if normalized:
|
||||
requested_domain = getattr(obj, "requested_domain", None)
|
||||
if requested_domain is not None:
|
||||
requested_domain.name = normalized
|
||||
requested_domain.save()
|
||||
else:
|
||||
requested_domain = Domain.objects.create(name=normalized)
|
||||
obj.requested_domain = requested_domain
|
||||
obj.save()
|
||||
|
||||
obj.save()
|
||||
normalized = Domain.normalize(
|
||||
self.cleaned_data["alternative_domain"], "gov", blank=True
|
||||
)
|
||||
if normalized:
|
||||
# TODO: ability to update existing records
|
||||
obj.alternative_domains.create(website=normalized)
|
||||
|
||||
def from_database(self, obj):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
requested_domain = getattr(obj, "requested_domain", None)
|
||||
if requested_domain is not None:
|
||||
self.initial["requested_domain"] = requested_domain.sld
|
||||
|
||||
alternative_domain = obj.alternative_domains.first()
|
||||
if alternative_domain is not None:
|
||||
self.initial["alternative_domain"] = alternative_domain.sld
|
||||
|
||||
requested_domain = forms.CharField(label="What .gov domain do you want?")
|
||||
alternative_domain = forms.CharField(
|
||||
required=False,
|
||||
label="Are there other domains you’d like if we can’t give you your first "
|
||||
|
@ -330,10 +331,29 @@ class DotGovDomainForm(RegistrarForm):
|
|||
|
||||
|
||||
class PurposeForm(RegistrarForm):
|
||||
purpose_field = forms.CharField(label="Purpose", widget=forms.Textarea())
|
||||
purpose = forms.CharField(label="Purpose", widget=forms.Textarea())
|
||||
|
||||
|
||||
class YourContactForm(RegistrarForm):
|
||||
def to_database(self, obj):
|
||||
"""Adds this form's cleaned data to `obj` and saves `obj`."""
|
||||
if not self.is_valid():
|
||||
return
|
||||
contact = getattr(obj, "submitter", None)
|
||||
if contact is not None:
|
||||
super().to_database(contact)
|
||||
else:
|
||||
contact = Contact()
|
||||
super().to_database(contact)
|
||||
obj.submitter = contact
|
||||
obj.save()
|
||||
|
||||
def from_database(self, obj):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
contact = getattr(obj, "submitter", None)
|
||||
if contact is not None:
|
||||
super().from_database(contact)
|
||||
|
||||
first_name = forms.CharField(label="First name/given name")
|
||||
middle_name = forms.CharField(
|
||||
required=False,
|
||||
|
@ -346,6 +366,27 @@ class YourContactForm(RegistrarForm):
|
|||
|
||||
|
||||
class OtherContactsForm(RegistrarForm):
|
||||
def to_database(self, obj):
|
||||
"""Adds this form's cleaned data to `obj` and saves `obj`."""
|
||||
if not self.is_valid():
|
||||
return
|
||||
obj.save()
|
||||
|
||||
# TODO: ability to handle multiple contacts
|
||||
contact = obj.other_contacts.filter(email=self.cleaned_data["email"]).first()
|
||||
if contact is not None:
|
||||
super().to_database(contact)
|
||||
else:
|
||||
contact = Contact()
|
||||
super().to_database(contact)
|
||||
obj.other_contacts.add(contact)
|
||||
|
||||
def from_database(self, obj):
|
||||
"""Initializes this form's fields with values gotten from `obj`."""
|
||||
other_contacts = obj.other_contacts.first()
|
||||
if other_contacts is not None:
|
||||
super().from_database(other_contacts)
|
||||
|
||||
first_name = forms.CharField(label="First name/given name")
|
||||
middle_name = forms.CharField(
|
||||
required=False,
|
||||
|
@ -358,7 +399,7 @@ class OtherContactsForm(RegistrarForm):
|
|||
|
||||
|
||||
class SecurityEmailForm(RegistrarForm):
|
||||
email = forms.EmailField(
|
||||
security_email = forms.EmailField(
|
||||
required=False,
|
||||
label="Security email",
|
||||
)
|
||||
|
@ -366,77 +407,104 @@ class SecurityEmailForm(RegistrarForm):
|
|||
|
||||
class AnythingElseForm(RegistrarForm):
|
||||
anything_else = forms.CharField(
|
||||
required=False, label="Anything else we should know", widget=forms.Textarea()
|
||||
required=False,
|
||||
label="Anything else we should know",
|
||||
widget=forms.Textarea(),
|
||||
)
|
||||
|
||||
|
||||
class RequirementsForm(RegistrarForm):
|
||||
agree_check = forms.BooleanField(
|
||||
is_policy_acknowledged = forms.BooleanField(
|
||||
label="I read and agree to the .gov domain requirements."
|
||||
)
|
||||
|
||||
|
||||
# Empty class for the review page which gets included as part of the form, but does not
|
||||
# have any form fields itself
|
||||
class ReviewForm(RegistrarForm):
|
||||
"""
|
||||
Empty class for the review page.
|
||||
|
||||
It gets included as part of the form, but does not have any form fields itself.
|
||||
"""
|
||||
|
||||
def to_database(self, _):
|
||||
"""This form has no data. Do nothing."""
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
# List of forms in our wizard. Each entry is a tuple of a name and a form
|
||||
# subclass
|
||||
class Step:
|
||||
"""Names for each page of the application wizard."""
|
||||
|
||||
ORGANIZATION_TYPE = "organization_type"
|
||||
ORGANIZATION_FEDERAL = "organization_federal"
|
||||
ORGANIZATION_ELECTION = "organization_election"
|
||||
ORGANIZATION_CONTACT = "organization_contact"
|
||||
AUTHORIZING_OFFICIAL = "authorizing_official"
|
||||
CURRENT_SITES = "current_sites"
|
||||
DOTGOV_DOMAIN = "dotgov_domain"
|
||||
PURPOSE = "purpose"
|
||||
YOUR_CONTACT = "your_contact"
|
||||
OTHER_CONTACTS = "other_contacts"
|
||||
SECURITY_EMAIL = "security_email"
|
||||
ANYTHING_ELSE = "anything_else"
|
||||
REQUIREMENTS = "requirements"
|
||||
REVIEW = "review"
|
||||
|
||||
|
||||
# List of forms in our wizard.
|
||||
# Each entry is a tuple of a name and a form subclass
|
||||
FORMS = [
|
||||
("organization_type", OrganizationTypeForm),
|
||||
("organization_federal", OrganizationFederalForm),
|
||||
("organization_election", OrganizationElectionForm),
|
||||
("organization_contact", OrganizationContactForm),
|
||||
("authorizing_official", AuthorizingOfficialForm),
|
||||
("current_sites", CurrentSitesForm),
|
||||
("dotgov_domain", DotGovDomainForm),
|
||||
("purpose", PurposeForm),
|
||||
("your_contact", YourContactForm),
|
||||
("other_contacts", OtherContactsForm),
|
||||
("security_email", SecurityEmailForm),
|
||||
("anything_else", AnythingElseForm),
|
||||
("requirements", RequirementsForm),
|
||||
("review", ReviewForm),
|
||||
(Step.ORGANIZATION_TYPE, OrganizationTypeForm),
|
||||
(Step.ORGANIZATION_FEDERAL, OrganizationFederalForm),
|
||||
(Step.ORGANIZATION_ELECTION, OrganizationElectionForm),
|
||||
(Step.ORGANIZATION_CONTACT, OrganizationContactForm),
|
||||
(Step.AUTHORIZING_OFFICIAL, AuthorizingOfficialForm),
|
||||
(Step.CURRENT_SITES, CurrentSitesForm),
|
||||
(Step.DOTGOV_DOMAIN, DotGovDomainForm),
|
||||
(Step.PURPOSE, PurposeForm),
|
||||
(Step.YOUR_CONTACT, YourContactForm),
|
||||
(Step.OTHER_CONTACTS, OtherContactsForm),
|
||||
(Step.SECURITY_EMAIL, SecurityEmailForm),
|
||||
(Step.ANYTHING_ELSE, AnythingElseForm),
|
||||
(Step.REQUIREMENTS, RequirementsForm),
|
||||
(Step.REVIEW, ReviewForm),
|
||||
]
|
||||
|
||||
# Dict to match up the right template with the right step. Keys here must
|
||||
# match the first elements of the tuples in FORMS
|
||||
# Dict to match up the right template with the right step.
|
||||
TEMPLATES = {
|
||||
"organization_type": "application_org_type.html",
|
||||
"organization_federal": "application_org_federal.html",
|
||||
"organization_election": "application_org_election.html",
|
||||
"organization_contact": "application_org_contact.html",
|
||||
"authorizing_official": "application_authorizing_official.html",
|
||||
"current_sites": "application_current_sites.html",
|
||||
"dotgov_domain": "application_dotgov_domain.html",
|
||||
"purpose": "application_purpose.html",
|
||||
"your_contact": "application_your_contact.html",
|
||||
"other_contacts": "application_other_contacts.html",
|
||||
"security_email": "application_security_email.html",
|
||||
"anything_else": "application_anything_else.html",
|
||||
"requirements": "application_requirements.html",
|
||||
"review": "application_review.html",
|
||||
Step.ORGANIZATION_TYPE: "application_org_type.html",
|
||||
Step.ORGANIZATION_FEDERAL: "application_org_federal.html",
|
||||
Step.ORGANIZATION_ELECTION: "application_org_election.html",
|
||||
Step.ORGANIZATION_CONTACT: "application_org_contact.html",
|
||||
Step.AUTHORIZING_OFFICIAL: "application_authorizing_official.html",
|
||||
Step.CURRENT_SITES: "application_current_sites.html",
|
||||
Step.DOTGOV_DOMAIN: "application_dotgov_domain.html",
|
||||
Step.PURPOSE: "application_purpose.html",
|
||||
Step.YOUR_CONTACT: "application_your_contact.html",
|
||||
Step.OTHER_CONTACTS: "application_other_contacts.html",
|
||||
Step.SECURITY_EMAIL: "application_security_email.html",
|
||||
Step.ANYTHING_ELSE: "application_anything_else.html",
|
||||
Step.REQUIREMENTS: "application_requirements.html",
|
||||
Step.REVIEW: "application_review.html",
|
||||
}
|
||||
|
||||
# We need to pass our page titles as context to the templates, indexed
|
||||
# by the step names
|
||||
# We need to pass our page titles as context to the templates
|
||||
TITLES = {
|
||||
"organization_type": "Type of organization",
|
||||
"organization_federal": "Type of organization — Federal",
|
||||
"organization_election": "Type of organization — Election board",
|
||||
"organization_contact": "Organization name and mailing address",
|
||||
"authorizing_official": "Authorizing official",
|
||||
"current_sites": "Organization website",
|
||||
"dotgov_domain": ".gov domain",
|
||||
"purpose": "Purpose of your domain",
|
||||
"your_contact": "Your contact information",
|
||||
"other_contacts": "Other contacts for your domain",
|
||||
"security_email": "Security email for public use",
|
||||
"anything_else": "Anything else we should know?",
|
||||
"requirements": "Requirements for registration and operation of .gov domains",
|
||||
"review": "Review and submit your domain request",
|
||||
Step.ORGANIZATION_TYPE: "Type of organization",
|
||||
Step.ORGANIZATION_FEDERAL: "Type of organization — Federal",
|
||||
Step.ORGANIZATION_ELECTION: "Type of organization — Election board",
|
||||
Step.ORGANIZATION_CONTACT: "Organization name and mailing address",
|
||||
Step.AUTHORIZING_OFFICIAL: "Authorizing official",
|
||||
Step.CURRENT_SITES: "Organization website",
|
||||
Step.DOTGOV_DOMAIN: ".gov domain",
|
||||
Step.PURPOSE: "Purpose of your domain",
|
||||
Step.YOUR_CONTACT: "Your contact information",
|
||||
Step.OTHER_CONTACTS: "Other contacts for your domain",
|
||||
Step.SECURITY_EMAIL: "Security email for public use",
|
||||
Step.ANYTHING_ELSE: "Anything else we should know?",
|
||||
Step.REQUIREMENTS: "Requirements for registration and operation of .gov domains",
|
||||
Step.REVIEW: "Review and submit your domain request",
|
||||
}
|
||||
|
||||
|
||||
|
@ -456,6 +524,10 @@ class ApplicationWizard(LoginRequiredMixin, NamedUrlSessionWizardView):
|
|||
domain applications. Each form in the sequence has its own URL and
|
||||
the progress through the form is stored in the Django session (thus
|
||||
"NamedUrlSessionWizardView").
|
||||
|
||||
Caution: due to the redirect performed by using NamedUrlSessionWizardView,
|
||||
many methods, such as `process_step`, are called TWICE per request. For
|
||||
this reason, methods in this class need to be idempotent.
|
||||
"""
|
||||
|
||||
form_list = FORMS
|
||||
|
@ -495,42 +567,97 @@ class ApplicationWizard(LoginRequiredMixin, NamedUrlSessionWizardView):
|
|||
context["is_federal"] = self._is_federal()
|
||||
return context
|
||||
|
||||
def forms_to_object(self, form_dict: dict) -> DomainApplication:
|
||||
"""Unpack the form responses onto the model object properties."""
|
||||
def get_application_object(self) -> DomainApplication:
|
||||
"""
|
||||
Attempt to match the current wizard with a DomainApplication.
|
||||
|
||||
Will create an application if none exists.
|
||||
"""
|
||||
if "application_id" in self.storage.extra_data:
|
||||
id = self.storage.extra_data["application_id"]
|
||||
try:
|
||||
return DomainApplication.objects.get(
|
||||
creator=self.request.user,
|
||||
pk=id,
|
||||
)
|
||||
except DomainApplication.DoesNotExist:
|
||||
logger.debug("Application id %s did not have a DomainApplication" % id)
|
||||
|
||||
application = DomainApplication.objects.create(creator=self.request.user)
|
||||
|
||||
# organization type information
|
||||
organization_type_data = form_dict["organization_type"].cleaned_data
|
||||
application.organization_type = organization_type_data["organization_type"]
|
||||
|
||||
# federal branch information may not exist
|
||||
federal_branch_data = form_dict.get("organization_federal")
|
||||
if federal_branch_data is not None:
|
||||
federal_branch_data = federal_branch_data.cleaned_data
|
||||
application.federal_branch = federal_branch_data["federal_type"]
|
||||
|
||||
# election board information may not exist.
|
||||
election_board_data = form_dict.get("organization_election")
|
||||
if election_board_data is not None:
|
||||
election_board_data = election_board_data.cleaned_data
|
||||
application.is_election_office = election_board_data["is_election_board"]
|
||||
|
||||
# contact information
|
||||
contact_data = form_dict["organization_contact"].cleaned_data
|
||||
application.organization_name = contact_data["organization_name"]
|
||||
application.street_address = contact_data["address_line1"]
|
||||
# TODO: add the rest of these fields when they are created in the forms
|
||||
|
||||
# This isn't really the requested_domain field
|
||||
# but we need something in this field to make the form submittable
|
||||
requested_site, _ = Domain.objects.get_or_create(
|
||||
name=contact_data["organization_name"] + ".gov"
|
||||
)
|
||||
application.requested_domain = requested_site
|
||||
self.storage.extra_data["application_id"] = application.id
|
||||
return application
|
||||
|
||||
def forms_to_database(
|
||||
self, forms: dict = None, form: RegistrarForm = None
|
||||
) -> DomainApplication:
|
||||
"""
|
||||
Unpack the form responses onto the model object properties.
|
||||
|
||||
Saves the application to the database.
|
||||
"""
|
||||
application = self.get_application_object()
|
||||
|
||||
if forms:
|
||||
itr = forms
|
||||
elif form:
|
||||
itr = {"form": form}
|
||||
else:
|
||||
raise TypeError("forms and form cannot both be None")
|
||||
|
||||
for form in itr.values():
|
||||
if form is not None and hasattr(form, "to_database"):
|
||||
form.to_database(application)
|
||||
|
||||
return application
|
||||
|
||||
def process_step(self, form):
|
||||
"""
|
||||
Hook called on every POST request, if the form is valid.
|
||||
|
||||
Do not manipulate the form data here.
|
||||
"""
|
||||
# save progress
|
||||
self.forms_to_database(form=form)
|
||||
return self.get_form_step_data(form)
|
||||
|
||||
def get_form(self, step=None, data=None, files=None):
|
||||
"""This method constructs the form for a given step."""
|
||||
form = super().get_form(step, data, files)
|
||||
|
||||
# restore from database, but only if a record has already
|
||||
# been associated with this wizard instance
|
||||
if "application_id" in self.storage.extra_data:
|
||||
application = self.get_application_object()
|
||||
form.from_database(application)
|
||||
return form
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""This method handles POST requests."""
|
||||
step = self.steps.current
|
||||
# always call super() first, to do important pre-processing
|
||||
rendered = super().post(*args, **kwargs)
|
||||
# if user opted to save their progress,
|
||||
# return them to the page they were already on
|
||||
button = self.request.POST.get("submit_button", None)
|
||||
if button == "save":
|
||||
return self.render_goto_step(step)
|
||||
# otherwise, proceed as normal
|
||||
return rendered
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""This method handles GET requests."""
|
||||
current_url = resolve(self.request.path_info).url_name
|
||||
# always call super(), it handles important redirect logic
|
||||
rendered = super().get(*args, **kwargs)
|
||||
# if user visited via an "edit" url, associate the id of the
|
||||
# application they are trying to edit to this wizard instance
|
||||
if current_url == "edit-application" and "id" in kwargs:
|
||||
self.storage.extra_data["application_id"] = kwargs["id"]
|
||||
return rendered
|
||||
|
||||
def done(self, form_list, form_dict, **kwargs):
|
||||
application = self.forms_to_object(form_dict)
|
||||
"""Called when the data for every form is submitted and validated."""
|
||||
application = self.forms_to_database(forms=form_dict)
|
||||
application.submit() # change the status to submitted
|
||||
application.save()
|
||||
logger.debug("Application object saved: %s", application.id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue