Skip to content

Commit 5f3f41c

Browse files
committed
Move SexAtBirthResponse to its own model
1 parent 516168e commit 5f3f41c

File tree

7 files changed

+130
-32
lines changed

7 files changed

+130
-32
lines changed

lung_cancer_screening/questions/forms/sex_at_birth_form.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
from django import forms
22

33
from ...nhsuk_forms.choice_field import ChoiceField
4-
from ..models.response_set import ResponseSet, SexAtBirthValues
4+
from ..models.sex_at_birth_response import SexAtBirthResponse, SexAtBirthValues
55

66

77
class SexAtBirthForm(forms.ModelForm):
88

99
def __init__(self, *args, **kwargs):
1010
super().__init__(*args, **kwargs)
1111

12-
self.fields["sex_at_birth"] = ChoiceField(
12+
self.fields["value"] = ChoiceField(
1313
choices=SexAtBirthValues.choices,
1414
widget=forms.RadioSelect,
1515
label="What was your sex at birth?",
@@ -24,5 +24,5 @@ def __init__(self, *args, **kwargs):
2424
)
2525

2626
class Meta:
27-
model = ResponseSet
28-
fields = ['sex_at_birth']
27+
model = SexAtBirthResponse
28+
fields = ['value']
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Generated manually to create SexAtBirthResponse and copy data
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
def copy_sex_at_birth_data(apps, schema_editor):
8+
with schema_editor.connection.cursor() as cursor:
9+
cursor.execute("""
10+
INSERT INTO questions_sexatbirthresponse (created_at, updated_at, value, response_set_id)
11+
SELECT NOW(), NOW(), sex_at_birth, id
12+
FROM questions_responseset
13+
WHERE sex_at_birth IS NOT NULL
14+
ON CONFLICT (response_set_id) DO NOTHING
15+
""")
16+
17+
18+
def reverse_copy_sex_at_birth_data(apps, schema_editor):
19+
with schema_editor.connection.cursor() as cursor:
20+
cursor.execute("""
21+
UPDATE questions_responseset rs
22+
SET sex_at_birth = s.value
23+
FROM questions_sexatbirthresponse s
24+
WHERE rs.id = s.response_set_id
25+
""")
26+
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
('questions', '0031_respiratoryconditionsresponse'),
32+
]
33+
34+
operations = [
35+
migrations.CreateModel(
36+
name='SexAtBirthResponse',
37+
fields=[
38+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
39+
('created_at', models.DateTimeField(auto_now_add=True)),
40+
('updated_at', models.DateTimeField(auto_now=True)),
41+
('value', models.CharField(choices=[('F', 'Female'), ('M', 'Male')], max_length=1)),
42+
('response_set', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='sex_at_birth_response', to='questions.responseset')),
43+
],
44+
options={
45+
'abstract': False,
46+
},
47+
),
48+
migrations.RunPython(copy_sex_at_birth_data, reverse_copy_sex_at_birth_data),
49+
migrations.RemoveField(
50+
model_name='responseset',
51+
name='sex_at_birth',
52+
),
53+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from django.db import models
2+
3+
from .base import BaseModel
4+
from .response_set import ResponseSet
5+
6+
7+
class SexAtBirthValues(models.TextChoices):
8+
FEMALE = "F", 'Female'
9+
MALE = "M", 'Male'
10+
11+
12+
class SexAtBirthResponse(BaseModel):
13+
response_set = models.OneToOneField(ResponseSet, on_delete=models.CASCADE, related_name='sex_at_birth_response')
14+
value = models.CharField(max_length=1, choices=SexAtBirthValues.choices)
Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,53 @@
11
from django.test import TestCase
22

3-
from ...factories.user_factory import UserFactory
4-
from ....models.response_set import ResponseSet, SexAtBirthValues
3+
from ...factories.response_set_factory import ResponseSetFactory
4+
from ....models.sex_at_birth_response import SexAtBirthResponse, SexAtBirthValues
55
from ....forms.sex_at_birth_form import SexAtBirthForm
66

77
class TestSexAtBirthForm(TestCase):
88
def setUp(self):
9-
self.user = UserFactory()
10-
self.response_set = ResponseSet(user=self.user)
9+
self.response_set = ResponseSetFactory()
10+
self.response = SexAtBirthResponse.objects.create(
11+
response_set=self.response_set,
12+
value=SexAtBirthValues.MALE
13+
)
1114

1215

1316
def test_is_valid_with_a_valid_value(self):
1417
form = SexAtBirthForm(
15-
instance=self.response_set,
18+
instance=self.response,
1619
data={
17-
"sex_at_birth": SexAtBirthValues.FEMALE
20+
"value": SexAtBirthValues.FEMALE
1821
}
1922
)
2023
self.assertTrue(form.is_valid())
2124
self.assertEqual(
22-
form.cleaned_data["sex_at_birth"],
25+
form.cleaned_data["value"],
2326
SexAtBirthValues.FEMALE.value
2427
)
2528

2629
def test_is_invalid_with_an_invalid_value(self):
2730
form = SexAtBirthForm(
28-
instance=self.response_set,
31+
instance=self.response,
2932
data={
30-
"sex_at_birth": "invalid"
33+
"value": "invalid"
3134
}
3235
)
3336
self.assertFalse(form.is_valid())
3437
self.assertEqual(
35-
form.errors["sex_at_birth"],
38+
form.errors["value"],
3639
["Select a valid choice. invalid is not one of the available choices."]
3740
)
3841

3942
def test_is_invalid_when_no_option_is_selected(self):
4043
form = SexAtBirthForm(
41-
instance=self.response_set,
44+
instance=self.response,
4245
data={
43-
"sex_at_birth": None
46+
"value": None
4447
}
4548
)
4649
self.assertFalse(form.is_valid())
4750
self.assertEqual(
48-
form.errors["sex_at_birth"],
51+
form.errors["value"],
4952
["Select your sex at birth"]
5053
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.test import TestCase
2+
3+
from ...factories.response_set_factory import ResponseSetFactory
4+
from ....models.sex_at_birth_response import SexAtBirthResponse, SexAtBirthValues
5+
6+
7+
class TestSexAtBirthResponse(TestCase):
8+
def test_has_response_set_as_foreign_key(self):
9+
response_set = ResponseSetFactory()
10+
response = SexAtBirthResponse.objects.create(
11+
response_set=response_set,
12+
value=SexAtBirthValues.MALE
13+
)
14+
15+
self.assertEqual(response.response_set, response_set)
16+
17+
def test_has_value_as_string(self):
18+
response_set = ResponseSetFactory()
19+
response = SexAtBirthResponse.objects.create(
20+
response_set=response_set,
21+
value=SexAtBirthValues.MALE
22+
)
23+
24+
self.assertIsInstance(response.value, str)

lung_cancer_screening/questions/tests/unit/views/test_sex_at_birth.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
from django.utils import timezone
55

66
from .helpers.authentication import login_user
7-
from lung_cancer_screening.questions.models.response_set import (
8-
SexAtBirthValues
9-
)
7+
from lung_cancer_screening.questions.models.sex_at_birth_response import SexAtBirthResponse, SexAtBirthValues
108

119

1210
class TestGetSexAtBirth(TestCase):
@@ -54,7 +52,7 @@ class TestPostSexAtBirth(TestCase):
5452
def setUp(self):
5553
self.user = login_user(self.client)
5654

57-
self.valid_params = {"sex_at_birth": SexAtBirthValues.FEMALE}
55+
self.valid_params = {"value": SexAtBirthValues.FEMALE}
5856

5957
def test_post_redirects_if_the_user_is_not_logged_in(self):
6058
self.client.logout()
@@ -82,7 +80,7 @@ def test_post_creates_unsubmitted_response_set_when_no_response_set_exists(
8280
self.assertEqual(self.user.responseset_set.count(), 1)
8381
self.assertEqual(response_set.submitted_at, None)
8482
self.assertEqual(
85-
response_set.sex_at_birth, self.valid_params["sex_at_birth"]
83+
SexAtBirthResponse.objects.get(response_set=response_set).value, self.valid_params["value"]
8684
)
8785
self.assertEqual(response_set.user, self.user)
8886

@@ -98,7 +96,7 @@ def test_post_updates_unsubmitted_response_set_when_one_exists(self):
9896
self.assertEqual(self.user.responseset_set.count(), 1)
9997
self.assertEqual(response_set.submitted_at, None)
10098
self.assertEqual(
101-
response_set.sex_at_birth, self.valid_params["sex_at_birth"]
99+
SexAtBirthResponse.objects.get(response_set=response_set).value, self.valid_params["value"]
102100
)
103101
self.assertEqual(response_set.user, self.user)
104102

@@ -120,7 +118,7 @@ def test_post_creates_new_unsubmitted_response_set_when_submitted_exists_over_ye
120118
response_set = self.user.responseset_set.last()
121119
self.assertEqual(response_set.submitted_at, None)
122120
self.assertEqual(
123-
response_set.sex_at_birth, self.valid_params["sex_at_birth"]
121+
SexAtBirthResponse.objects.get(response_set=response_set).value, self.valid_params["value"]
124122
)
125123
self.assertEqual(response_set.user, self.user)
126124

@@ -146,7 +144,7 @@ def test_post_stores_a_valid_response_for_the_user(self):
146144

147145
response_set = self.user.responseset_set.first()
148146
self.assertEqual(
149-
response_set.sex_at_birth, self.valid_params["sex_at_birth"]
147+
SexAtBirthResponse.objects.get(response_set=response_set).value, self.valid_params["value"]
150148
)
151149
self.assertEqual(response_set.user, self.user)
152150

@@ -161,7 +159,7 @@ def test_post_redirects_to_the_gender_path(self):
161159
def test_post_responds_with_422_if_the_response_fails_to_create(self):
162160
response = self.client.post(
163161
reverse("questions:sex_at_birth"),
164-
{"sex_at_birth": "something not in list"}
162+
{"value": "something not in list"}
165163
)
166164

167165
self.assertEqual(response.status_code, 422)
@@ -171,7 +169,7 @@ def test_post_renders_the_sex_at_birth_page_with_an_error_if_form_invalid(
171169
):
172170
response = self.client.post(
173171
reverse("questions:sex_at_birth"),
174-
{"sex_at_birth": "something not in list"}
172+
{"value": "something not in list"}
175173
)
176174

177175
self.assertContains(

lung_cancer_screening/questions/views/sex_at_birth.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,31 @@
55

66
from .mixins.ensure_response_set import EnsureResponseSet
77
from ..forms.sex_at_birth_form import SexAtBirthForm
8+
from ..models.sex_at_birth_response import SexAtBirthResponse
89

910

1011
class SexAtBirthView(LoginRequiredMixin, EnsureResponseSet, View):
1112
def get(self, request):
13+
response, _ = SexAtBirthResponse.objects.get_or_build(
14+
response_set=request.response_set
15+
)
1216
return render_template(
1317
request,
14-
SexAtBirthForm(instance=request.response_set)
18+
SexAtBirthForm(instance=response)
1519
)
1620

1721
def post(self, request):
22+
response, _ = SexAtBirthResponse.objects.get_or_build(
23+
response_set=request.response_set
24+
)
1825
form = SexAtBirthForm(
19-
instance=request.response_set,
26+
instance=response,
2027
data=request.POST
2128
)
2229

2330
if form.is_valid():
24-
response_set = request.response_set
25-
response_set.sex_at_birth = form.cleaned_data["sex_at_birth"]
26-
response_set.save()
31+
response.value = form.cleaned_data["value"]
32+
response.save()
2733
return redirect(reverse("questions:gender"))
2834
else:
2935
return render_template(

0 commit comments

Comments
 (0)