-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #1018: Make project details editing work again #1019
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your proposed solution solves only half the problem. Initially, I implemented this that way because I want to make sure, you can't change the questionnaire when there is data in the project (though my original solution is incredibly shortsighted). The reason I wanted to block changing questionnaires not only by hiding the form field in the template but also in the view was that I wanted to have several layers where this is checked and rejected.
I would suggest adding a check to the ProjectEditDetails
form; for instance into the clean_questionnaire
to raise a validation error. I won't have any effect on what it displayed to the user, but we will be on the safe side in case the form is reused at some point. I can't implement that and add it to your PR if you want (after all it's me who caused the issue).
@@ -652,7 +652,7 @@ def get_initial(self): | |||
|
|||
def post(self, *args, **kwargs): | |||
if self.get_project().has_records: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The if condition is not necessary anymore. So I would get rid of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there can still be a use for this condition except that the super().post()
should be outside. Right now, neither the form nor the view checks that the user has not attempted to update the questionnaire when there are already records.
So maybe the condition should be moved to the form and the form (save()
) checks that the questionnaire is unchanged or is not provided in the POST data when the project has records.
@@ -934,7 +933,7 @@ class ProjectEditDetailsTest(ViewTestCase, UserTestCase, | |||
} | |||
|
|||
def setup_models(self): | |||
self.project = ProjectFactory.create(current_questionnaire='abc') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree with this. We should still test that the view does not update the questionnaire if the project has data. So we should write a test that rejects the update, even though with the current template it's not possible to upload a new questionnaire. My rationale behind it is that if we change the template for some reason and accidentally enable to update the questionnaire, the update will still be rejected from the view, no matter hat the template looks like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense. But as I mentioned in another comment, neither the form nor the view does any rejection. So we would need to add that rejection functionality before we can test it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, it seems that the original line of code (ProjectFactory.create(current_questionnaire='abc')
) does not actually create a project with a valid questionnaire. We would need to create a Questionnaire
instance too in setup_models
.
Another code observation. Please refer to the following lines of code: https://github.com/Cadasta/cadasta-platform/blob/bugfix/%231018/cadasta/organization/forms.py#L353-L361 Given that the current template does not include the questionnaire form fields when there are records, |
I added necessary checks to the form also taking into account Eugene's remarks. Tests have both added to views and forms covering various scenarios. Adding @seav as reviewer for my changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have left some change requests and comments.
@@ -357,7 +368,7 @@ def save(self, *args, **kwargs): | |||
original_file=original_file, | |||
project=self.instance | |||
) | |||
else: | |||
elif not self.instance.has_records: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this condition really correct? This condition will be evaluated only if new_form
is false which can be due to two things:
- There was an existing
questionnaire
but it was removed or it remained empty (questionnaire == ''
) - The field was missing which implies that the questionnaire should remain unchanged (
questionnaire == None
).
Now the condition checks whether the project already has records and then clears out current_questionnaire
when there are no records. I can only consider scenario 1 above to be valid in this case. For scenario 2, current_questionnaire
should remain unchanged. I suggest adding an additional condition to check that new_form is not None
.
@@ -933,7 +934,7 @@ class ProjectEditDetailsTest(ViewTestCase, UserTestCase, | |||
} | |||
|
|||
def setup_models(self): | |||
self.project = ProjectFactory.create() | |||
self.project = ProjectFactory.create(current_questionnaire='abc') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take note that this project creation does not actually create any valid Questionnaire
instances. This means that when the view's get_initial()
method is executed, Questionnaire.DoesNotExist
will be thrown and initial['questionnaire']
will never be populated. This may have an effect later on when the form is submitted and we are comparing new_form
with current_form
.
SpatialUnitFactory.create(project=self.project) | ||
user = UserFactory.create() | ||
assign_policies(user) | ||
post_data = self.post_data.copy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You copied post_data
here then deleted the questionnaire
entry in the next line. But you never actually used this modified post_data
in the request. Based on how I understand django-skivvy to work, the call to request()
later on will still use the original self.post_data
that still contains the questionnaire
entry.
If I understand the test intent correctly, the idea is to try and submit a POST request which does not include the questionnaire field (questionnaire == None
). This implies that the questionnaire should remain unchanged which is a valid scenario. Therefore the test should have checked for a 302 status with updated project details, not 200 and unchanged project details.
Good points @seav. I addressed the issues in the latest commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These latest changes are OK with me. The ball is now in @bjohare's court.
0e1478d
to
136b191
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything seems to be working.
Proposed changes in this pull request
super().post()
.questionnaire
is removed from the defaultpost_data
in order to simulate the missing questionnaire fields in the template if the project has records.When should this PR be merged
Soon.
Risks
None foreseen.
Follow up actions
None.
Checklist (for reviewing)
General
migration
label if a new migration is added.Functionality
Code
Tests
Documentation