Skip to content
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

Added modifications to polls and stories API #851

Merged
merged 10 commits into from
Jan 12, 2022
50 changes: 50 additions & 0 deletions ureport/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,31 @@ def get_images(self, obj):
for image in obj.get_featured_images()
]

# Function to use ?fields and ?exclude API calls for specific attributes in stories
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
request = kwargs.get('context', {}).get('request')
str_exclude_fields = request.GET.get('exclude', '') if request else None
str_fields = request.GET.get('fields', '') if request else None
fields = str_fields.split(',') if str_fields else None
exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None

# Instantiate the superclass normally
super(StoryReadSerializer, self).__init__(*args, **kwargs)

if exclude_fields is not None:
# Drop any fields that are specified in the `exclude` argument.
exclude_allowed = set(exclude_fields)
existing = set(self.fields)
for field_name in exclude_allowed:
self.fields.pop(field_name)
elif fields is not None:
allowed_fields = set(fields)
existing_data = set(self.fields)
for field_names in existing_data - allowed_fields:
self.fields.pop(field_names)


class Meta:
model = Story
fields = (
Expand All @@ -122,6 +147,31 @@ class PollReadSerializer(serializers.ModelSerializer):
category = CategoryReadSerializer()
questions = SerializerMethodField()

# Function to use ?fields and ?exclude API calls for specific attributes in polls
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
request = kwargs.get('context', {}).get('request')
str_exclude_fields = request.GET.get('exclude', '') if request else None
str_fields = request.GET.get('fields', '') if request else None
fields = str_fields.split(',') if str_fields else None
exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None

# Instantiate the superclass normally
super(PollReadSerializer, self).__init__(*args, **kwargs)

if exclude_fields is not None:
# Drop any fields that are specified in the `exclude` argument.
exclude_allowed = set(exclude_fields)
print('exclude_allowed :',exclude_allowed)
alviriseup marked this conversation as resolved.
Show resolved Hide resolved
existing = set(self.fields)
for field_name in exclude_allowed:
self.fields.pop(field_name)
elif fields is not None:
allowed_fields = set(fields)
existing_data = set(self.fields)
for field_names in existing_data - allowed_fields:
self.fields.pop(field_names)

def get_questions(self, obj):
questions = []
for question in obj.get_questions():
Expand Down
170 changes: 170 additions & 0 deletions ureport/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,32 @@ def test_polls_by_org_list_with_flow_uuid_parameter(self):
self.assertEqual(response.data["count"], 1)
self.assertEqual(response.data["results"][0]["title"], "registration")

def test_polls_by_org_list_with_fields_parameter(self):
url = "/api/v1/polls/org/%d/?fields=%s" % (self.uganda.pk, "title")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
count_polls = Poll.objects.filter(org=self.uganda, is_active=True, has_synced=True).count()
self.assertEqual(response.data["count"], count_polls)
poll = [self.second_featured_poll, self.first_featured_poll, self.another_poll, self.reg_poll]
alviriseup marked this conversation as resolved.
Show resolved Hide resolved
for i in range(count_polls):
self.assertEqual(response.data["results"][i]["title"], poll[i].title)

def test_polls_by_org_list_with_exclude_parameter(self):
url = "/api/v1/polls/org/%d/?exclude=%s,%s,%s,%s,%s,%s" % (self.uganda.pk, "flow_uuid","title","category","poll_date","modified_on","created_on")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
count_polls = Poll.objects.filter(org=self.uganda, is_active=True, has_synced=True).count()
poll = self.reg_poll
self.assertEqual(response.data["count"], count_polls)
self.assertDictEqual(
response.data["results"][3],
dict(
id=poll.pk,
org=poll.org_id,
questions=[],
),
)

def test_featured_poll_by_org_list_when_featured_polls_exists(self):
url = "/api/v1/polls/org/%d/featured/" % self.uganda.pk
response = self.client.get(url)
Expand All @@ -410,6 +436,13 @@ def test_featured_poll_by_org_list_when_featured_polls_exists(self):
self.assertEqual(response.data["count"], 2)
self.assertTrue(response.data["results"][0]["modified_on"] > response.data["results"][1]["modified_on"])

def test_featured_poll_by_org_list_with_fields_parameter_when_featured_polls_exists(self):
url = "/api/v1/polls/org/%d/featured/?fields=%s" % (self.uganda.pk, "created_on")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["count"], 2)
self.assertTrue(response.data["results"][0]["created_on"] > response.data["results"][1]["created_on"])

def test_featured_poll_by_org_list_when_no_featured_polls_exists(self):
url = "/api/v1/polls/org/%d/featured/" % self.nigeria.pk
response = self.client.get(url)
Expand Down Expand Up @@ -500,6 +533,112 @@ def test_single_poll(self):
),
)

def test_single_poll_with_fields_parameter(self):
url = "/api/v1/polls/%d/?fields=%s,%s,%s" % (self.reg_poll.pk, "id", "title", "questions")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
poll = self.reg_poll
self.assertDictEqual(
response.data,
dict(
id=poll.pk,
title=poll.title,
questions=[],
),
)

with patch("ureport.polls.models.PollQuestion.get_results") as mock_get_results:
mock_get_results.return_value = [dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT")]

poll_question = self.create_poll_question(self.superuser, self.reg_poll, "What's on mind? :)", "uuid1")

response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(
response.data,
dict(
id=poll.pk,
title=poll.title,
questions=[
dict(
id=poll_question.pk,
ruleset_uuid="uuid1",
title="What's on mind? :)",
results=dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT"),
results_by_age=[dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT")],
results_by_gender=[dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT")],
results_by_location=[
dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT")
],
)
],
),
)

poll_question.is_active = False
poll_question.save()

response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(
response.data,
dict(
id=poll.pk,
title=poll.title,
questions=[],
),
)

def test_single_poll_with_exclude_parameter(self):
url = "/api/v1/polls/%d/?exclude=%s,%s,%s,%s" % (self.reg_poll.pk, "id","title","category", "questions")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
poll = self.reg_poll
self.assertDictEqual(
response.data,
dict(
flow_uuid=poll.flow_uuid,
org=poll.org_id,
poll_date=poll.poll_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
modified_on=poll.modified_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
created_on=poll.created_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
),
)

with patch("ureport.polls.models.PollQuestion.get_results") as mock_get_results:
mock_get_results.return_value = [dict(set=20, unset=10, open_ended=False, categories="CATEGORIES-DICT")]

poll_question = self.create_poll_question(self.superuser, self.reg_poll, "What's on mind? :)", "uuid1")

response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(
response.data,
dict(
flow_uuid=poll.flow_uuid,
org=poll.org_id,
created_on=poll.created_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
modified_on=poll.modified_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
poll_date=poll.poll_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
),
)

poll_question.is_active = False
poll_question.save()

response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(
response.data,
dict(
flow_uuid=poll.flow_uuid,
org=poll.org_id,
poll_date=poll.poll_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
modified_on=poll.modified_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
created_on=poll.created_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
),
)

def test_news_item_by_org_list(self):
url = "/api/v1/news/org/%d/" % self.uganda.pk
url1 = "/api/v1/news/org/%d/" % self.nigeria.pk
Expand Down Expand Up @@ -602,6 +741,37 @@ def test_single_story(self):
dict(name=story.category.name, image_url=CategoryReadSerializer().get_image_url(story.category)),
)

def test_single_story_with_fields_parameter(self):
url = "/api/v1/stories/%d/?fields=%s" % (self.uganda_story.pk, "content")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
story = self.uganda_story
self.assertDictEqual(
response.data,
dict(
content=story.content,
),
)

def test_single_story_with_exclude_parameter(self):
url = "/api/v1/stories/%d/?exclude=%s,%s,%s,%s" % (self.uganda_story.pk, "content", "featured", "images", "category")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
story = self.uganda_story
self.assertDictEqual(
response.data,
dict(
id=story.pk,
title=story.title,
video_id=story.video_id,
audio_link=story.audio_link,
summary=story.summary,
tags=story.tags,
org=story.org_id,
created_on=story.created_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
),
)

def test_dashblock_by_org_list(self):
url_uganda = "/api/v1/dashblocks/org/%d/" % self.uganda.pk
url_nigeria = "/api/v1/dashblocks/org/%d/" % self.nigeria.pk
Expand Down
99 changes: 99 additions & 0 deletions ureport/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,26 @@ class PollList(BaseListAPIView):
...
]
}


If you want to get polls with only specific attributes:

Example:

GET /api/v1/polls/org/{org}/?fields=title,flow_uuid

Response is polls with only title and flow_uuid attributes.


If you want to get polls without specific attributes:

Example:

GET /api/v1/polls/org/{org}/?exclude=title,flow_uuid

Response is polls without title and flow_uuid attributes.


"""

serializer_class = PollReadSerializer
Expand Down Expand Up @@ -395,6 +415,26 @@ class PollDetails(RetrieveAPIView):
},
"created_on": "2015-09-02T08:53:30.313251Z"
}


If you want to get a poll with only specific attributes:

Example:

GET /api/v1/polls/{id}/?fields=title,flow_uuid

Response is a poll with only title and flow_uuid attributes.


If you want to get a poll without specific attributes:

Example:

GET /api/v1/polls/{id}/?exclude=title,flow_uuid

Response is a poll without title and flow_uuid attributes.


"""

serializer_class = PollReadSerializer
Expand Down Expand Up @@ -532,6 +572,26 @@ class FeaturedPollList(BaseListAPIView):
...
]
}


If you want to get the featured poll with only specific attributes:

Example:

GET /api/v1/polls/org/{org}/featured/?fields=title,flow_uuid

Response is the featured poll with only title and flow_uuid attributes.


If you want to get the featured poll without specific attributes:

Example:

GET /api/v1/polls/org/{org}/featured/?exclude=title,flow_uuid

Response is the featured poll without title and flow_uuid attributes.


"""

serializer_class = PollReadSerializer
Expand Down Expand Up @@ -829,6 +889,26 @@ class StoryList(BaseListAPIView):
},
...
}


If you want to get stories with only specific attributes:

Example:

GET /api/v1/stories/org/{org}/?fields=title,content

Response is stories with only title and content attributes.


If you want to get stories without specific attributes:

Example:

GET /api/v1/stories/org/{org}/?exclude=title,content

Response is stories without title and content attributes.


"""

serializer_class = StoryReadSerializer
Expand Down Expand Up @@ -866,6 +946,25 @@ class StoryDetails(RetrieveAPIView):
"name": "tests"
}
}

If you want to get a story with only specific attributes:

Example:

GET /api/v1/stories/{id}/?fields=title,content

Response is a story with only title and content attributes.


If you want to get a story without specific attributes:

Example:

GET /api/v1/stories/{id}/?exclude=title,content

Response is a story without title and content attributes.


"""

serializer_class = StoryReadSerializer
Expand Down