From 08dcdb85cd4c4b35af387b333fcc83a3c98ece7b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 3 Jan 2024 12:40:05 -0500 Subject: [PATCH] wip --- src/registrar/forms/application_wizard.py | 54 ++++++----- .../templates/application_other_contacts.html | 4 + src/registrar/views/application.py | 94 +++---------------- 3 files changed, 48 insertions(+), 104 deletions(-) diff --git a/src/registrar/forms/application_wizard.py b/src/registrar/forms/application_wizard.py index 59c044353..ec6dd99d4 100644 --- a/src/registrar/forms/application_wizard.py +++ b/src/registrar/forms/application_wizard.py @@ -126,6 +126,9 @@ class RegistrarFormSet(forms.BaseFormSet): for db_obj, post_data in zip_longest(query, self.forms, fillvalue=None): cleaned = post_data.cleaned_data if post_data is not None else {} + logger.info(f"in _to_database for {self.__class__.__name__}") + logger.info(db_obj) + logger.info(cleaned) # matching database object exists, update it if db_obj is not None and cleaned: if should_delete(cleaned): @@ -136,7 +139,7 @@ class RegistrarFormSet(forms.BaseFormSet): db_obj.save() # no matching database object, create it - elif db_obj is None and cleaned: + elif db_obj is None and cleaned and not cleaned.get('delete', False): kwargs = pre_create(db_obj, cleaned) getattr(obj, join).create(**kwargs) @@ -601,7 +604,7 @@ class OtherContactsForm(RegistrarForm): def mark_form_for_deletion(self): logger.info("removing form data from other contact") - self.data = {} + # self.data = {} self.form_data_marked_for_deletion = True def clean(self): @@ -615,25 +618,26 @@ class OtherContactsForm(RegistrarForm): if self.form_data_marked_for_deletion: # Set form_is_empty to True initially - form_is_empty = True - for name, field in self.fields.items(): - # get the value of the field from the widget - value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) - # if any field in the submitted form is not empty, set form_is_empty to False - if value is not None and value != "": - form_is_empty = False + # form_is_empty = True + # for name, field in self.fields.items(): + # # get the value of the field from the widget + # value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) + # # if any field in the submitted form is not empty, set form_is_empty to False + # if value is not None and value != "": + # form_is_empty = False - if form_is_empty: - # clear any errors raised by the form fields - # (before this clean() method is run, each field - # performs its own clean, which could result in - # errors that we wish to ignore at this point) - # - # NOTE: we cannot just clear() the errors list. - # That causes problems. - for field in self.fields: - if field in self.errors: - del self.errors[field] + # if form_is_empty: + # # clear any errors raised by the form fields + # # (before this clean() method is run, each field + # # performs its own clean, which could result in + # # errors that we wish to ignore at this point) + # # + # # NOTE: we cannot just clear() the errors list. + # # That causes problems. + for field in self.fields: + if field in self.errors: + del self.errors[field] + return {'delete': True} return self.cleaned_data @@ -650,9 +654,16 @@ class BaseOtherContactsFormSet(RegistrarFormSet): self.formset_data_marked_for_deletion = False super().__init__(*args, **kwargs) + def pre_update(self, db_obj, cleaned): + """Code to run before an item in the formset is saved.""" + + for key, value in cleaned.items(): + setattr(db_obj, key, value) + def should_delete(self, cleaned): empty = (isinstance(v, str) and (v.strip() == "" or v is None) for v in cleaned.values()) - return all(empty) + logger.info(f"should_delete => {all(empty)}") + return all(empty) or self.formset_data_marked_for_deletion def to_database(self, obj: DomainApplication): logger.info("to_database called on BaseOtherContactsFormSet") @@ -686,6 +697,7 @@ OtherContactsFormSet = forms.formset_factory( absolute_max=1500, # django default; use `max_num` to limit entries min_num=1, validate_min=True, + # can_delete=True, formset=BaseOtherContactsFormSet, ) diff --git a/src/registrar/templates/application_other_contacts.html b/src/registrar/templates/application_other_contacts.html index 9d1873803..d07873608 100644 --- a/src/registrar/templates/application_other_contacts.html +++ b/src/registrar/templates/application_other_contacts.html @@ -29,6 +29,10 @@

Organization contact {{ forloop.counter }} (optional)

+ {% if forms.1.can_delete %} + {{ form.DELETE }} + {% endif %} + {% input_with_errors form.first_name %} {% input_with_errors form.middle_name %} diff --git a/src/registrar/views/application.py b/src/registrar/views/application.py index 24a3de7d0..6ae890da4 100644 --- a/src/registrar/views/application.py +++ b/src/registrar/views/application.py @@ -1,6 +1,6 @@ import logging -from django.http import Http404, HttpResponse, HttpResponseRedirect +from django.http import Http404, HttpResponse, HttpResponseRedirect, QueryDict from django.shortcuts import redirect, render from django.urls import resolve, reverse from django.utils.safestring import mark_safe @@ -412,6 +412,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView): """ for form in forms: if form is not None and hasattr(form, "to_database"): + logger.info(f"saving form {form.__class__.__name__}") form.to_database(self.application) @@ -486,87 +487,6 @@ class OtherContacts(ApplicationWizard): template_name = "application_other_contacts.html" forms = [forms.OtherContactsYesNoForm, forms.OtherContactsFormSet, forms.NoOtherContactsForm] - # def post(self, request, *args, **kwargs) -> HttpResponse: - # """This method handles POST requests.""" - # # Log the keys and values of request.POST - # for key, value in request.POST.items(): - # logger.info("Key: %s, Value: %s", key, value) - # # if accessing this class directly, redirect to the first step - # if self.__class__ == ApplicationWizard: - # return self.goto(self.steps.first) - - # # which button did the user press? - # button: str = request.POST.get("submit_button", "") - - # forms = self.get_forms(use_post=True) - # # forms is now set as follows: - # # forms.0 is yes no form - # # forms.1 - forms.length-1 are other contacts forms - # # forms.length is no other contacts form - # yes_no_form = forms[0] - # other_contacts_forms = forms[1] - # no_other_contacts_form = forms[2] - - # all_forms_valid = True - # # test first for yes_no_form validity - # if yes_no_form.is_valid(): - # logger.info("yes no form is valid") - # # test for has_contacts - # if yes_no_form.cleaned_data.get('has_other_contacts'): - # logger.info("has other contacts") - # # remove data from no_other_contacts_form and set - # # form to always_valid - # no_other_contacts_form.remove_form_data() - # # test that the other_contacts_forms and no_other_contacts_forms are valid - # if not self.is_valid(forms[1:]): - # all_forms_valid = False - # else: - # logger.info("has no other contacts") - # # remove data from each other_contacts_form - # other_contacts_forms.remove_form_data() - # # test that the other_contacts_forms and no_other_contacts_forms are valid - # if not self.is_valid(forms[1:]): - # all_forms_valid = False - # else: - # all_forms_valid = False - - # if all_forms_valid: - # logger.info("all forms are valid") - # # always save progress - # self.save(forms) - # else: - # context = self.get_context_data() - # context["forms"] = forms - # return render(request, self.template_name, context) - - # # if user opted to save their progress, - # # return them to the page they were already on - # if button == "save": - # messages.success(request, "Your progress has been saved!") - # return self.goto(self.steps.current) - # # if user opted to save progress and return, - # # return them to the home page - # if button == "save_and_return": - # return HttpResponseRedirect(reverse("home")) - # # otherwise, proceed as normal - # return self.goto_next_step() - - # def post(self, request, *args, **kwargs) -> HttpResponse: - # parent_form = forms.OtherContactsYesNoForm(request.POST, **kwargs) - # other_contacts_formset = forms.OtherContactsFormSet(request.POST, **kwargs) - # no_other_contacts_form = forms.NoOtherContactsForm(request.POST, **kwargs) - - # logger.info("in post") - # has_other_contacts_selected = parent_form.data.get('other_contacts-has_other_contacts') - # logger.info(f"has other contacts = {has_other_contacts_selected}") - # if has_other_contacts_selected: - # logger.info("has other contacts") - # other_contacts_formset.data = {} - # else: - # logger.info("doesn't have other contacts") - # no_other_contacts_form.data = {} - # return super().post(request, *args, **kwargs) - def is_valid(self, forms: list) -> bool: """Overrides default behavior defined in ApplicationWizard. Depending on value in other_contacts_yes_no_form, marks forms in @@ -593,7 +513,15 @@ class OtherContacts(ApplicationWizard): logger.info("has no other contacts") # remove data from each other_contacts_form other_contacts_forms.mark_formset_for_deletion() - # test that the other_contacts_forms and no_other_contacts_forms are valid + # set the delete data to on in each form + # Create a mutable copy of the QueryDict + # mutable_data = QueryDict(mutable=True) + # mutable_data.update(self.request.POST.copy()) + + # for i, form in enumerate(other_contacts_forms.forms): + # form_prefix = f'other_contacts-{i}' + # mutable_data[f'{form_prefix}-deleted'] = 'on' + # other_contacts_forms.forms[i].data = mutable_data.copy() all_forms_valid = all(form.is_valid() for form in forms[1:]) else: all_forms_valid = False