diff --git a/opentech/apply/funds/models/submissions.py b/opentech/apply/funds/models/submissions.py index 866c57428b034800c956fd6298005f00ab566769..4047078370ef35cfac2c437304e758f36f90e112 100644 --- a/opentech/apply/funds/models/submissions.py +++ b/opentech/apply/funds/models/submissions.py @@ -1,4 +1,5 @@ import os +from functools import partialmethod from django.conf import settings from django.contrib.auth import get_user_model @@ -192,6 +193,38 @@ class AddTransitions(models.base.ModelBase): return super().__new__(cls, name, bases, attrs, **kwargs) +class ApplicationSubmissionMetaclass(AddTransitions): + def __new__(cls, name, bases, attrs, **kwargs): + cls = super().__new__(cls, name, bases, attrs, **kwargs) + + # We want to access the redered display of the required fields. + # Treat in similar way to django's get_FIELD_display + for required_name in REQUIRED_BLOCK_NAMES: + partial_method_name = f'_{required_name}_method' + # We need to generate the partial method and the wrap it in property so + # we can access the required fields like normal fields. e.g. self.title + # Partial method requires __get__ to be called in order to bind it to the + # class properly this is using the <name> -> _<name>_method -> _get_REQUIRED_value + # call chain which instantiates each method correctly at the cost of an extra + # lookup + setattr( + cls, + partial_method_name, + partialmethod(cls._get_REQUIRED_value, name=required_name), + ) + setattr( + cls, + f'{required_name}', + property(getattr(cls, partial_method_name)), + ) + setattr( + cls, + f'get_{required_name}_display', + partialmethod(cls._get_REQUIRED_display, name=required_name), + ) + return cls + + class ApplicationSubmission( WorkflowHelpers, BaseStreamForm, @@ -494,13 +527,6 @@ class ApplicationSubmission( def get_absolute_url(self): return reverse('funds:submissions:detail', args=(self.id,)) - def __getattribute__(self, item): - # __getattribute__ allows correct error handling from django compared to __getattr__ - # fall back to values defined on the data - if item in REQUIRED_BLOCK_NAMES: - return self.form_data[item] - return super().__getattribute__(item) - def __str__(self): return f'{self.title} from {self.full_name} for {self.page.title}' @@ -510,7 +536,7 @@ class ApplicationSubmission( # Methods for accessing data on the submission def get_data(self): - # Updated for JSONField + # Updated for JSONField - Not used but base get_data will error form_data = self.form_data.copy() form_data.update({ 'submit_time': self.submit_time, @@ -596,6 +622,12 @@ class ApplicationSubmission( ] return mark_safe(''.join(answers)) + def _get_REQUIRED_display(self, name): + return self.render_answer(name) + + def _get_REQUIRED_value(self, name): + return self.form_data[name] + @receiver(post_transition, sender=ApplicationSubmission) def log_status_update(sender, **kwargs): diff --git a/opentech/apply/funds/templates/funds/includes/rendered_answers.html b/opentech/apply/funds/templates/funds/includes/rendered_answers.html index e5b7f88b2266a90a71dc67d714ee0dbfa40e05b9..b6d461a8543ff4820302aae2cb1de8b812829717 100644 --- a/opentech/apply/funds/templates/funds/includes/rendered_answers.html +++ b/opentech/apply/funds/templates/funds/includes/rendered_answers.html @@ -8,7 +8,7 @@ <div> <h5>Project Duration</h5> - <p>{{ object.value }}</p> + <p>{{ object.get_duration_display }}</p> </div> <div>