From ba23b7fc8596de9c86aef1bf39e508e606b445b1 Mon Sep 17 00:00:00 2001 From: alviriseup Date: Mon, 3 Jan 2022 18:55:08 +0600 Subject: [PATCH 1/9] Added functions for fields and exclude API call --- .../ureport/api/serializers_20220103184452.py | 220 ++++++++++++++ .../ureport/api/serializers_20220103185012.py | 271 ++++++++++++++++++ ureport/api/serializers.py | 51 ++++ 3 files changed, 542 insertions(+) create mode 100644 .history/ureport/api/serializers_20220103184452.py create mode 100644 .history/ureport/api/serializers_20220103185012.py diff --git a/.history/ureport/api/serializers_20220103184452.py b/.history/ureport/api/serializers_20220103184452.py new file mode 100644 index 000000000..e6b684205 --- /dev/null +++ b/.history/ureport/api/serializers_20220103184452.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +import json + +import six +from rest_framework import serializers +from rest_framework.fields import SerializerMethodField +from sorl.thumbnail import get_thumbnail + +from dash.categories.models import Category +from dash.dashblocks.models import DashBlock +from dash.orgs.models import Org +from dash.stories.models import Story +from ureport.assets.models import Image +from ureport.news.models import NewsItem, Video +from ureport.polls.models import Poll + + +def generate_absolute_url_from_file(request, file, thumbnail_geometry): + thumnail = get_thumbnail(file, thumbnail_geometry, crop="center", quality=99) + return request.build_absolute_uri(thumnail.url) + + +class CategoryReadSerializer(serializers.ModelSerializer): + image_url = SerializerMethodField() + + def get_image_url(self, obj): + image = None + if obj.image: + image = obj.image + elif obj.get_first_image(): + image = obj.get_first_image() + if image: + return generate_absolute_url_from_file(self.context["request"], image, "800x600") + return None + + class Meta: + model = Category + fields = ("image_url", "name") + + +class OrgReadSerializer(serializers.ModelSerializer): + logo_url = SerializerMethodField() + gender_stats = SerializerMethodField() + age_stats = SerializerMethodField() + registration_stats = SerializerMethodField() + occupation_stats = SerializerMethodField() + reporters_count = SerializerMethodField() + timezone = SerializerMethodField() + + class Meta: + model = Org + fields = ( + "id", + "logo_url", + "name", + "language", + "subdomain", + "domain", + "timezone", + "gender_stats", + "age_stats", + "registration_stats", + "occupation_stats", + "reporters_count", + ) + + def get_logo_url(self, obj): + if obj.get_logo(): + return generate_absolute_url_from_file(self.context["request"], obj.get_logo(), "x180") + return None + + def get_gender_stats(self, obj): + return obj.get_gender_stats() + + def get_age_stats(self, obj): + return json.loads(obj.get_age_stats()) + + def get_registration_stats(self, obj): + return json.loads(obj.get_registration_stats()) + + def get_occupation_stats(self, obj): + return json.loads(obj.get_occupation_stats()) + + def get_reporters_count(self, obj): + return obj.get_reporters_count() + + def get_timezone(self, obj): + return six.text_type(obj.timezone) + + +class StoryReadSerializer(serializers.ModelSerializer): + category = CategoryReadSerializer() + images = SerializerMethodField() + + def get_images(self, obj): + return [ + generate_absolute_url_from_file(self.context["request"], image.image, "800x600") + for image in obj.get_featured_images() + ] + + class Meta: + model = Story + fields = ( + "id", + "title", + "featured", + "summary", + "content", + "video_id", + "audio_link", + "tags", + "org", + "images", + "category", + "created_on", + ) + + +class PollReadSerializer(serializers.ModelSerializer): + category = CategoryReadSerializer() + questions = SerializerMethodField() + + def get_questions(self, obj): + questions = [] + for question in obj.get_questions(): + open_ended = question.is_open_ended() + results_dict = dict(open_ended=open_ended) + results = question.get_results() + if results: + results_dict = results[0] + results_by_age = question.get_results(segment=dict(age="Age")) + results_by_gender = question.get_results(segment=dict(gender="Gender")) + results_by_state = question.get_results(segment=dict(location="State")) + + question_data = { + "id": question.pk, + "ruleset_uuid": question.flow_result.result_uuid, + "title": question.title, + "results": results_dict, + } + + if not open_ended: + question_data["results_by_age"] = results_by_age + question_data["results_by_gender"] = results_by_gender + question_data["results_by_location"] = results_by_state + + questions.append(question_data) + + return questions + + class Meta: + model = Poll + fields = ("id", "flow_uuid", "title", "org", "category", "poll_date", "modified_on", "created_on", "questions") + + +class NewsItemReadSerializer(serializers.ModelSerializer): + short_description = SerializerMethodField() + category = CategoryReadSerializer() + + def get_short_description(self, obj): + return obj.short_description() + + class Meta: + model = NewsItem + fields = ("id", "short_description", "category", "title", "description", "link", "org", "created_on") + + +class VideoReadSerializer(serializers.ModelSerializer): + category = CategoryReadSerializer() + + class Meta: + model = Video + fields = ("id", "category", "title", "description", "video_id", "org", "created_on") + + +class ImageReadSerializer(serializers.ModelSerializer): + image_url = SerializerMethodField() + + def get_image_url(self, obj): + return generate_absolute_url_from_file(self.context["request"], obj.image, "x180") + + class Meta: + model = Image + fields = ("id", "image_url", "image_type", "org", "name", "created_on") + + +class DashblockReadSerializer(serializers.ModelSerializer): + dashblock_type = SerializerMethodField() + image_url = SerializerMethodField() + path = SerializerMethodField() + + def get_image_url(self, obj): + if obj.image: + return generate_absolute_url_from_file(self.context["request"], obj.image, "800x600") + return None + + def get_dashblock_type(self, obj): + return obj.dashblock_type.slug + + def get_path(self, obj): + return obj.link + + class Meta: + model = DashBlock + fields = ( + "id", + "org", + "dashblock_type", + "priority", + "title", + "summary", + "content", + "image_url", + "color", + "path", + "video_id", + "tags", + ) diff --git a/.history/ureport/api/serializers_20220103185012.py b/.history/ureport/api/serializers_20220103185012.py new file mode 100644 index 000000000..a8f134914 --- /dev/null +++ b/.history/ureport/api/serializers_20220103185012.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +import json + +import six +from rest_framework import serializers +from rest_framework.fields import SerializerMethodField +from sorl.thumbnail import get_thumbnail + +from dash.categories.models import Category +from dash.dashblocks.models import DashBlock +from dash.orgs.models import Org +from dash.stories.models import Story +from ureport.assets.models import Image +from ureport.news.models import NewsItem, Video +from ureport.polls.models import Poll + + +def generate_absolute_url_from_file(request, file, thumbnail_geometry): + thumnail = get_thumbnail(file, thumbnail_geometry, crop="center", quality=99) + return request.build_absolute_uri(thumnail.url) + + +class CategoryReadSerializer(serializers.ModelSerializer): + image_url = SerializerMethodField() + + def get_image_url(self, obj): + image = None + if obj.image: + image = obj.image + elif obj.get_first_image(): + image = obj.get_first_image() + if image: + return generate_absolute_url_from_file(self.context["request"], image, "800x600") + return None + + class Meta: + model = Category + fields = ("image_url", "name") + + +class OrgReadSerializer(serializers.ModelSerializer): + logo_url = SerializerMethodField() + gender_stats = SerializerMethodField() + age_stats = SerializerMethodField() + registration_stats = SerializerMethodField() + occupation_stats = SerializerMethodField() + reporters_count = SerializerMethodField() + timezone = SerializerMethodField() + + class Meta: + model = Org + fields = ( + "id", + "logo_url", + "name", + "language", + "subdomain", + "domain", + "timezone", + "gender_stats", + "age_stats", + "registration_stats", + "occupation_stats", + "reporters_count", + ) + + def get_logo_url(self, obj): + if obj.get_logo(): + return generate_absolute_url_from_file(self.context["request"], obj.get_logo(), "x180") + return None + + def get_gender_stats(self, obj): + return obj.get_gender_stats() + + def get_age_stats(self, obj): + return json.loads(obj.get_age_stats()) + + def get_registration_stats(self, obj): + return json.loads(obj.get_registration_stats()) + + def get_occupation_stats(self, obj): + return json.loads(obj.get_occupation_stats()) + + def get_reporters_count(self, obj): + return obj.get_reporters_count() + + def get_timezone(self, obj): + return six.text_type(obj.timezone) + + +class StoryReadSerializer(serializers.ModelSerializer): + category = CategoryReadSerializer() + images = SerializerMethodField() + + def get_images(self, obj): + return [ + generate_absolute_url_from_file(self.context["request"], image.image, "800x600") + for image in obj.get_featured_images() + ] + + # Function to use ?fields and ?exclude API calls for specific attributes in stories + # this is for which we can exclude any field + def __init__(self, *args, **kwargs): + # Don't pass the 'fields' arg up to the superclass + request = kwargs.get('context', {}).get('request') + str_fields = request.GET.get('exclude', '') if request else None + str_exclude_fields = request.GET.get('fields', '') if request else None + exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + fields = str_fields.split(',') if str_fields else None + + # Instantiate the superclass normally + super(StoryReadSerializer, self).__init__(*args, **kwargs) + + if fields is not None: + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + existing = set(self.fields) + for field_name in allowed: + self.fields.pop(field_name) + elif exclude_fields is not None: + allowed_fields = set(exclude_fields) + existing_data = set(self.fields) + for field_names in existing_data - allowed_fields: + self.fields.pop(field_names) + + + class Meta: + model = Story + fields = ( + "id", + "title", + "featured", + "summary", + "content", + "video_id", + "audio_link", + "tags", + "org", + "images", + "category", + "created_on", + ) + + +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_fields = request.GET.get('exclude', '') if request else None + str_exclude_fields = request.GET.get('fields', '') if request else None + exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + fields = str_fields.split(',') if str_fields else None + + # Instantiate the superclass normally + super(PollReadSerializer, self).__init__(*args, **kwargs) + + if fields is not None: + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + print('allowed :',allowed) + existing = set(self.fields) + for field_name in allowed: + self.fields.pop(field_name) + elif exclude_fields is not None: + allowed_fields = set(exclude_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(): + open_ended = question.is_open_ended() + results_dict = dict(open_ended=open_ended) + results = question.get_results() + if results: + results_dict = results[0] + results_by_age = question.get_results(segment=dict(age="Age")) + results_by_gender = question.get_results(segment=dict(gender="Gender")) + results_by_state = question.get_results(segment=dict(location="State")) + + question_data = { + "id": question.pk, + "ruleset_uuid": question.flow_result.result_uuid, + "title": question.title, + "results": results_dict, + } + + if not open_ended: + question_data["results_by_age"] = results_by_age + question_data["results_by_gender"] = results_by_gender + question_data["results_by_location"] = results_by_state + + questions.append(question_data) + + return questions + + class Meta: + model = Poll + fields = ("id", "flow_uuid", "title", "org", "category", "poll_date", "modified_on", "created_on", "questions") + + +class NewsItemReadSerializer(serializers.ModelSerializer): + short_description = SerializerMethodField() + category = CategoryReadSerializer() + + def get_short_description(self, obj): + return obj.short_description() + + class Meta: + model = NewsItem + fields = ("id", "short_description", "category", "title", "description", "link", "org", "created_on") + + +class VideoReadSerializer(serializers.ModelSerializer): + category = CategoryReadSerializer() + + class Meta: + model = Video + fields = ("id", "category", "title", "description", "video_id", "org", "created_on") + + +class ImageReadSerializer(serializers.ModelSerializer): + image_url = SerializerMethodField() + + def get_image_url(self, obj): + return generate_absolute_url_from_file(self.context["request"], obj.image, "x180") + + class Meta: + model = Image + fields = ("id", "image_url", "image_type", "org", "name", "created_on") + + +class DashblockReadSerializer(serializers.ModelSerializer): + dashblock_type = SerializerMethodField() + image_url = SerializerMethodField() + path = SerializerMethodField() + + def get_image_url(self, obj): + if obj.image: + return generate_absolute_url_from_file(self.context["request"], obj.image, "800x600") + return None + + def get_dashblock_type(self, obj): + return obj.dashblock_type.slug + + def get_path(self, obj): + return obj.link + + class Meta: + model = DashBlock + fields = ( + "id", + "org", + "dashblock_type", + "priority", + "title", + "summary", + "content", + "image_url", + "color", + "path", + "video_id", + "tags", + ) diff --git a/ureport/api/serializers.py b/ureport/api/serializers.py index e6b684205..a8f134914 100644 --- a/ureport/api/serializers.py +++ b/ureport/api/serializers.py @@ -100,6 +100,32 @@ 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 + # this is for which we can exclude any field + def __init__(self, *args, **kwargs): + # Don't pass the 'fields' arg up to the superclass + request = kwargs.get('context', {}).get('request') + str_fields = request.GET.get('exclude', '') if request else None + str_exclude_fields = request.GET.get('fields', '') if request else None + exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + fields = str_fields.split(',') if str_fields else None + + # Instantiate the superclass normally + super(StoryReadSerializer, self).__init__(*args, **kwargs) + + if fields is not None: + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + existing = set(self.fields) + for field_name in allowed: + self.fields.pop(field_name) + elif exclude_fields is not None: + allowed_fields = set(exclude_fields) + existing_data = set(self.fields) + for field_names in existing_data - allowed_fields: + self.fields.pop(field_names) + + class Meta: model = Story fields = ( @@ -122,6 +148,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_fields = request.GET.get('exclude', '') if request else None + str_exclude_fields = request.GET.get('fields', '') if request else None + exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + fields = str_fields.split(',') if str_fields else None + + # Instantiate the superclass normally + super(PollReadSerializer, self).__init__(*args, **kwargs) + + if fields is not None: + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + print('allowed :',allowed) + existing = set(self.fields) + for field_name in allowed: + self.fields.pop(field_name) + elif exclude_fields is not None: + allowed_fields = set(exclude_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(): From db4ed071327081e5eee56f84695247568dbb7f06 Mon Sep 17 00:00:00 2001 From: alviriseup Date: Mon, 3 Jan 2022 19:10:00 +0600 Subject: [PATCH 2/9] example for field and exclude API call --- .history/ureport/api/views_20220103184452.py | 990 ++++++++++++++++ .history/ureport/api/views_20220103190914.py | 1089 ++++++++++++++++++ ureport/api/views.py | 99 ++ 3 files changed, 2178 insertions(+) create mode 100644 .history/ureport/api/views_20220103184452.py create mode 100644 .history/ureport/api/views_20220103190914.py diff --git a/.history/ureport/api/views_20220103184452.py b/.history/ureport/api/views_20220103184452.py new file mode 100644 index 000000000..c8d48f495 --- /dev/null +++ b/.history/ureport/api/views_20220103184452.py @@ -0,0 +1,990 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +from rest_framework.generics import ListAPIView, RetrieveAPIView + +from django.db.models import Q + +from dash.dashblocks.models import DashBlock +from dash.orgs.models import Org +from dash.stories.models import Story +from ureport.api.serializers import ( + DashblockReadSerializer, + ImageReadSerializer, + NewsItemReadSerializer, + OrgReadSerializer, + PollReadSerializer, + StoryReadSerializer, + VideoReadSerializer, +) +from ureport.assets.models import Image +from ureport.news.models import NewsItem, Video +from ureport.polls.models import Poll + + +class OrgList(ListAPIView): + """ + This endpoint allows you to list orgs. + + ## Listing Orgs + + By making a ```GET``` request you can list all the organisations. Each org has the following attributes: + + * **id** - the ID of the org (int) + * **logo_url** - the LOGO_URL of the org (string) + * **name** - the NAME of the org (string) + * **language** - the LANGUAGE of the org (string) + * **subdomain** - the SUBDOMAIN of of this org (string) + * **domain** - the DOMAIN of of this org (string) + * **timezone** - the TIMEZONE of of this org (string) + + Example: + + GET /api/v1/orgs/ + + Response is the list of orgs: + + { + "count": 389, + "next": "/api/v1/polls/orgs/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", + "name": "test", + "language": "en", + "subdomain": "test", + "domain": "ureport.in", + "timezone": "Africa/Kampala" + "gender_stats": { + "female_count": 0, + "male_percentage": "---", + "female_percentage": "---", + "male_count": 0 + }, + "age_stats": [], + "registration_stats": [{"count": 0, "label": "07/06/15"}], + "occupation_stats": [] + }, + ... + } + """ + + serializer_class = OrgReadSerializer + queryset = Org.objects.filter(is_active=True) + + +class OrgDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single org. + + ## Get a single org + + Example: + + GET /api/v1/orgs/1/ + + Response is a single org with that ID: + + { + "id": 1, + "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", + "name": "test", + "language": "en", + "subdomain": "test", + "domain": "ureport.in", + "timezone": "Africa/Kampala" + "gender_stats": { + "female_count": 0, + "male_percentage": "---", + "female_percentage": "---", + "male_count": 0 + }, + "age_stats": [], + "registration_stats": [{"count": 0, "label": "07/06/15"}], + "occupation_stats": [] + } + """ + + serializer_class = OrgReadSerializer + queryset = Org.objects.filter(is_active=True) + + +class BaseListAPIView(ListAPIView): + def get_queryset(self): + q = self.model.objects.filter(is_active=True).order_by("-created_on") + if self.kwargs.get("org", None): + q = q.filter(org_id=self.kwargs.get("org")) + return q + + +class PollList(BaseListAPIView): + """ + This endpoint allows you to list polls. + + ## Listing Polls + + By making a ```GET``` request you can list all the polls for an organization, filtering them as needed. Each + poll has the following attributes: + + * **id** - the ID of the poll (int) + * **flow_uuid** - the FLOW_UUID of the run (string) (filterable: ```flow_uuid```) + * **title** - the TITLE of the poll (string) + * **org** - the ID of the org that owns this poll (int) + * **category** - the CATEGORIES of of this poll (dictionary) + + * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` + + Example: + + GET /api/v1/polls/org/1/ + + Response is the list of polls, most recent first: + + { + "count": 389, + "next": "/api/v1/polls/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "category": { + "image_url": null, + "name": "Education" + }, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + + + + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + + ] + + + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "poll_date": "2015-09-02T08:53:30.313251Z", + "modified_on": "2015-09-02T08:53:30.313251Z", + "created_on": "2015-09-02T08:53:30.313251Z" + } + ... + ] + } + """ + + serializer_class = PollReadSerializer + model = Poll + + def get_queryset(self): + q = super(PollList, self).get_queryset() + q = q.filter(is_active=True, has_synced=True).exclude(flow_uuid="") + if self.request.query_params.get("flow_uuid", None): + q = q.filter(flow_uuid=self.request.query_params.get("flow_uuid")) + + if self.request.query_params.get("sort", None) == "modified_on": + q = q.order_by("-modified_on") + + return q + + +class PollDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single poll. + + ## Get a single poll + + Example: + + GET /api/v1/polls/1/ + + Response is a single poll with that ID: + + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "category": { + "image_url": null, + "name": "Education" + }, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "created_on": "2015-09-02T08:53:30.313251Z" + } + """ + + serializer_class = PollReadSerializer + queryset = Poll.objects.filter(is_active=True, has_synced=True).exclude(flow_uuid="") + + +class FeaturedPollList(BaseListAPIView): + """ + This endpoint allows you to list all featured polls for an organisation. + + ## Listing Featured Polls + + * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` + + Example: + + GET /api/v1/polls/org/1/featured/ + + Response is a list of the featured polls, most recent first. \ + An empty list is returned if there are no polls with questions. + + { + "count": 389, + "next": "/api/v1/polls/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + + + + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + + ] + + + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "poll_date": "2015-09-02T08:53:30.313251Z", + "modified_on": "2015-09-02T08:53:30.313251Z", + "created_on": "2015-09-02T08:53:30.313251Z" + } + ... + ] + } + """ + + serializer_class = PollReadSerializer + model = Poll + + def get_queryset(self): + q = super(FeaturedPollList, self).get_queryset() + + if self.request.query_params.get("sort", None) == "modified_on": + q = ( + q.filter(is_active=True, has_synced=True) + .exclude(flow_uuid="") + .filter(is_featured=True) + .order_by("-modified_on") + ) + else: + q = ( + q.filter(is_active=True, has_synced=True) + .exclude(flow_uuid="") + .filter(is_featured=True) + .order_by("-created_on") + ) + return q + + +class NewsItemList(BaseListAPIView): + """ + This endpoint allows you to list news items. + + ## Listing news items + + By making a ```GET``` request you can list all the news items for an organization, filtering them as needed. Each + news item has the following attributes: + + * **id** - the ID of the item (int) + * **short_description** - the SHORT_DESCRIPTION of the news item (string) + * **title** - the TITLE of the news item (string) + * **org** - the ID of the org that owns this news item (int) + * **link** - the link to the source of this news item (string) + * **category** - the CATEGORY of of this news item (dictionary) + + Example: + + GET /api/v1/news/org/1/ + + Response is the list of news items of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/news/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "short_description": "This is a test news item that I want to use to test my api and speed of typing", + "title": "test", + "description": "This is a test news item that I want to use to test my api and speed of typing", + "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + """ + + serializer_class = NewsItemReadSerializer + model = NewsItem + + +class NewsItemDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single news item + + ## A single news item + Example: + + GET /api/v1/news/1/ + + Response is a single news item: + + { + "id": 1, + "short_description": "This is a test news item that I want to use to test my api and speed of typing", + "title": "test", + "description": "This is a test news item that I want to use to test my api and speed of typing", + "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + } + """ + + serializer_class = NewsItemReadSerializer + queryset = NewsItem.objects.filter(is_active=True) + + +class VideoList(BaseListAPIView): + """ + This endpoint allows you to list videos. + + ## Listing videos + + By making a ```GET``` request you can list all the videos for an organization, filtering them as needed. Each + video has the following attributes: + + * **id** - the ID of the video (int) + * **description** - the DESCRIPTION of the video (string) + * **title** - the TITLE of the video (string) + * **org** - the ID of the org that owns this video (int) + * **link** - the link to the source of this news item (string) + * **category** - the CATEGORY of of this news item (dictionary) + + Example: + + GET /api/v1/videos/org/1/ + + Response is the list of videos of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/videos/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "title": "test", + "description": "This guy is hating on the benz", + "video_id": "ZPJ64sTa7KI", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + """ + + serializer_class = VideoReadSerializer + model = Video + + +class VideoDetails(RetrieveAPIView): + """ + This endpoint allows you to a single video + + ## A single Video + + Example: + + GET /api/v1/videos/1/ + + Response is a single Video: + + { + "id": 1, + "title": "test", + "description": "This guy is hating on the benz", + "video_id": "ZPJ64sTa7KI", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + } + """ + + serializer_class = VideoReadSerializer + queryset = Video.objects.filter(is_active=True) + + +class ImageList(BaseListAPIView): + """ + This endpoint allows you to list assets. + + ## Listing assets + + By making a ```GET``` request you can list all the assets for an organization, filtering them as needed. Each + asset has the following attributes: + + * **id** - the ID of the asset (int) + * **image_type** - the IMAGE_TYPE of the asset (string) + * **title** - the TITLE of the asset (string) + * **org** - the ID of the org that owns this asset (int) + * **name** - the name of the asset (string) + + Example: + + GET /api/v1/assets/org/1/ + + Response is the list of assets of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/assets/org/1/?page=2", + "previous": null, + "results": [ + { + "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", + "image_type": "B", + "org": 1, + "name": "Image name" + }, + ... + } + """ + + serializer_class = ImageReadSerializer + model = Image + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(is_active=True, image_type="L") + + +class ImageDetails(RetrieveAPIView): + """ + This endpoint allows you to a single assets. + + ## A single asset + + Example: + + GET /api/v1/assets/1/ + + Response is a single asset: + + { + "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", + "image_type": "B", + "org": 1, + "name": "Image name" + } + """ + + serializer_class = ImageReadSerializer + queryset = Image.objects.filter(is_active=True, image_type="L") + + +class StoryList(BaseListAPIView): + """ + This endpoint allows you to list stories. + + ## Listing stories + + By making a ```GET``` request you can list all the stories for an organization, filtering them as needed. Each + story has the following attributes: + + * **id** - the ID of the story (int) + * **title** - the TITLE of the story (string) + * **featured** - whether the story if FEATURED or not (boolean) + * **org** - the ID of the org that owns this story (int) + * **summary** - the summary of the story (string) + * **content** - the content of the story (string), this can be containing HTML code data as the content is managed as WYSIWYG + * **video_id** - YouTube ID of the video in this story (string) + * **audio_link** - the AUDIO_LINK in this story (string) + * **tags** - the TAGS in this story (string) + * **images** - the IMAGES in this story (list of strings) + * **category** - the CATEGORY of the asset (dictionary) + + Example: + + GET /api/v1/stories/org/1/ + + Response is the list of stories of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/stories/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "title": "Test Story", + "featured": true, + "summary": "This is the summary of the story.", + "content": "This is the content of the story.", + "video_id": "", + "audio_link": null, + "tags": " test, story ", + "org": 1, + "images": [ + "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", + "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + """ + + serializer_class = StoryReadSerializer + model = Story + + +class StoryDetails(RetrieveAPIView): + """ + This endpoint allows you to a single story. + + ## A single story + + Example: + + GET /api/v1/stories/1/ + + Response is a single story: + + { + "id": 1, + "title": "Test Story", + "featured": true, + "summary": "This is the summary of the story.", + "content": "This is the content of the story.", + "video_id": "", + "audio_link": null, + "tags": " test, story ", + "org": 1, + "images": [ + "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", + "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + } + """ + + serializer_class = StoryReadSerializer + queryset = Story.objects.filter(is_active=True).filter(Q(attachment="") | Q(attachment=None)) + + +class DashBlockList(BaseListAPIView): + """ + This endpoint allows you to list dashblocks. + + ## Listing dashblocks + + By making a ```GET``` request you can list all the dashblocks for an organization, filtering them as needed. Each + dashblock has the following attributes: + + * **id** - the ID of the story (int) + * **org** - the ID of the org that owns this dashblock (int) + * **dashblock_type** - the type of the dashblock (string) filterable as `dashblock_type`. + * **priority** - the priority of the dashblock (int) + * **title** - the title of the dashblock (string) + * **summary** - the summary of the dashblock (string) + * **content** - the content of the dashblock (string), this can be containing HTML code data as the content is managed as WYSIWYG + * **image_url** - the image url of the dashblock image (string) + * **color** - the color of the dashblock (string) + * **path** - the path of the dashblock to use after the root URL (string) + * **video_id** - the video_id of the dashblock image (string) + * **tags** - the tags of the dashblock (string) + + + Example: + + GET /api/v1/dashblocks/org/1/ + + Response is the list of dashblocks of the organisation + { + "count": 13, + "next": "http://test.ureport.in/api/v1/dashblocks/org/1/?limit=10&offset=10", + "previous": null, + "results": [ + { + "id": 12, + "org": 1, + "dashblock_type": "photos", + "priority": 1, + "title": "CRC@30", + "summary": null, + "content": "Happy Child", + "image_url": "http://test.ureport.in/media/cache/ac/a7/aca7e7ae228e107b9186e77f222faabe.jpg", + "color": null, + "path": null, + "video_id": null, + "tags": null + }, + { + "id": 54, + "org": 1, + "dashblock_type": "photos", + "priority": 0, + "title": "World Mental Day Poll", + "summary": null, + "content": "", + "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", + "color": null, + "link": null, + "video_id": null, + "tags": null + } + ] + } + + """ + + serializer_class = DashblockReadSerializer + model = DashBlock + exclusive_params = ("dashblock_type",) + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(is_active=True).select_related("dashblock_type") + + def filter_queryset(self, queryset): + params = self.request.query_params + + # filter by UUID (optional) + d_type = params.get("dashblock_type") + if d_type: + queryset = queryset.filter(dashblock_type__slug=d_type) + + return queryset + + +class DashBlockDetails(RetrieveAPIView): + """ + This endpoint allows you to a single dashblock. + + ## A single dashblock + + Example: + + GET /api/v1/dashblocks/1/ + + Response is a single dashblock: + + { + "id": 1, + "org": 1, + "dashblock_type": "about", + "priority": 0, + "title": "About", + "summary": "U-report is a free SMS social monitoring.", + "content": "U-report is a free SMS social monitoring tool for community participation, designed to address issues that the population cares about.", + "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", + "color": null, + "link": null, + "video_id": null, + "tags": null + }, + """ + + serializer_class = DashblockReadSerializer + model = DashBlock + queryset = DashBlock.objects.filter(is_active=True) diff --git a/.history/ureport/api/views_20220103190914.py b/.history/ureport/api/views_20220103190914.py new file mode 100644 index 000000000..6d158bcbc --- /dev/null +++ b/.history/ureport/api/views_20220103190914.py @@ -0,0 +1,1089 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +from rest_framework.generics import ListAPIView, RetrieveAPIView + +from django.db.models import Q + +from dash.dashblocks.models import DashBlock +from dash.orgs.models import Org +from dash.stories.models import Story +from ureport.api.serializers import ( + DashblockReadSerializer, + ImageReadSerializer, + NewsItemReadSerializer, + OrgReadSerializer, + PollReadSerializer, + StoryReadSerializer, + VideoReadSerializer, +) +from ureport.assets.models import Image +from ureport.news.models import NewsItem, Video +from ureport.polls.models import Poll + + +class OrgList(ListAPIView): + """ + This endpoint allows you to list orgs. + + ## Listing Orgs + + By making a ```GET``` request you can list all the organisations. Each org has the following attributes: + + * **id** - the ID of the org (int) + * **logo_url** - the LOGO_URL of the org (string) + * **name** - the NAME of the org (string) + * **language** - the LANGUAGE of the org (string) + * **subdomain** - the SUBDOMAIN of of this org (string) + * **domain** - the DOMAIN of of this org (string) + * **timezone** - the TIMEZONE of of this org (string) + + Example: + + GET /api/v1/orgs/ + + Response is the list of orgs: + + { + "count": 389, + "next": "/api/v1/polls/orgs/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", + "name": "test", + "language": "en", + "subdomain": "test", + "domain": "ureport.in", + "timezone": "Africa/Kampala" + "gender_stats": { + "female_count": 0, + "male_percentage": "---", + "female_percentage": "---", + "male_count": 0 + }, + "age_stats": [], + "registration_stats": [{"count": 0, "label": "07/06/15"}], + "occupation_stats": [] + }, + ... + } + """ + + serializer_class = OrgReadSerializer + queryset = Org.objects.filter(is_active=True) + + +class OrgDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single org. + + ## Get a single org + + Example: + + GET /api/v1/orgs/1/ + + Response is a single org with that ID: + + { + "id": 1, + "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", + "name": "test", + "language": "en", + "subdomain": "test", + "domain": "ureport.in", + "timezone": "Africa/Kampala" + "gender_stats": { + "female_count": 0, + "male_percentage": "---", + "female_percentage": "---", + "male_count": 0 + }, + "age_stats": [], + "registration_stats": [{"count": 0, "label": "07/06/15"}], + "occupation_stats": [] + } + """ + + serializer_class = OrgReadSerializer + queryset = Org.objects.filter(is_active=True) + + +class BaseListAPIView(ListAPIView): + def get_queryset(self): + q = self.model.objects.filter(is_active=True).order_by("-created_on") + if self.kwargs.get("org", None): + q = q.filter(org_id=self.kwargs.get("org")) + return q + + +class PollList(BaseListAPIView): + """ + This endpoint allows you to list polls. + + ## Listing Polls + + By making a ```GET``` request you can list all the polls for an organization, filtering them as needed. Each + poll has the following attributes: + + * **id** - the ID of the poll (int) + * **flow_uuid** - the FLOW_UUID of the run (string) (filterable: ```flow_uuid```) + * **title** - the TITLE of the poll (string) + * **org** - the ID of the org that owns this poll (int) + * **category** - the CATEGORIES of of this poll (dictionary) + + * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` + + Example: + + GET /api/v1/polls/org/1/ + + Response is the list of polls, most recent first: + + { + "count": 389, + "next": "/api/v1/polls/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "category": { + "image_url": null, + "name": "Education" + }, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + + + + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + + ] + + + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "poll_date": "2015-09-02T08:53:30.313251Z", + "modified_on": "2015-09-02T08:53:30.313251Z", + "created_on": "2015-09-02T08:53:30.313251Z" + } + ... + ] + } + + + 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 + model = Poll + + def get_queryset(self): + q = super(PollList, self).get_queryset() + q = q.filter(is_active=True, has_synced=True).exclude(flow_uuid="") + if self.request.query_params.get("flow_uuid", None): + q = q.filter(flow_uuid=self.request.query_params.get("flow_uuid")) + + if self.request.query_params.get("sort", None) == "modified_on": + q = q.order_by("-modified_on") + + return q + + +class PollDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single poll. + + ## Get a single poll + + Example: + + GET /api/v1/polls/1/ + + Response is a single poll with that ID: + + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "category": { + "image_url": null, + "name": "Education" + }, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "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 + queryset = Poll.objects.filter(is_active=True, has_synced=True).exclude(flow_uuid="") + + +class FeaturedPollList(BaseListAPIView): + """ + This endpoint allows you to list all featured polls for an organisation. + + ## Listing Featured Polls + + * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` + + Example: + + GET /api/v1/polls/org/1/featured/ + + Response is a list of the featured polls, most recent first. \ + An empty list is returned if there are no polls with questions. + + { + "count": 389, + "next": "/api/v1/polls/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 2, + "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", + "title": "Food Poll", + "org": 1, + "questions": [ + { + "id": 14, + "title": "Are you hungry?", + "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", + "results": + { + "open_ended": false, + "set": 100, + "unset": 150, + "categories": [ + { + "count": 60, + "label": "Yes" + }, + { + "count": 30, + "label": "NO" + }, + { + "count": 10, + "label": "Thirsty" + }, + { + "count": 0, + "label": "Other" + }, + ] + } + }, + { + + + + "id": 16, + "title": "What would you like to eat", + "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", + "results": + { + "open_ended": true, + "set": 70, + "unset": 30, + "categories": [ + { + "count": 40, + "label": "Food" + }, + { + "count": 10, + "label": "Cake" + }, + { + "count": 15, + "label": "Fruits" + }, + { + "count": 5, + "label": "Coffee" + }, + ] + } + }, + { + "id": 17, + "title": "Where would you like to eat?", + "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", + "results": + { + "open_ended": false, + "set": 50, + "unset": 20, + "categories": [ + { + "count": 30, + "label": "Home" + }, + { + "count": 12, + "label": "Resto" + }, + { + "count": 5, + "label": "Fast Food" + }, + { + "count": 3, + "label": "Other" + }, + ] + } + } + + ] + + + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + }, + "poll_date": "2015-09-02T08:53:30.313251Z", + "modified_on": "2015-09-02T08:53:30.313251Z", + "created_on": "2015-09-02T08:53:30.313251Z" + } + ... + ] + } + + + 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 + model = Poll + + def get_queryset(self): + q = super(FeaturedPollList, self).get_queryset() + + if self.request.query_params.get("sort", None) == "modified_on": + q = ( + q.filter(is_active=True, has_synced=True) + .exclude(flow_uuid="") + .filter(is_featured=True) + .order_by("-modified_on") + ) + else: + q = ( + q.filter(is_active=True, has_synced=True) + .exclude(flow_uuid="") + .filter(is_featured=True) + .order_by("-created_on") + ) + return q + + +class NewsItemList(BaseListAPIView): + """ + This endpoint allows you to list news items. + + ## Listing news items + + By making a ```GET``` request you can list all the news items for an organization, filtering them as needed. Each + news item has the following attributes: + + * **id** - the ID of the item (int) + * **short_description** - the SHORT_DESCRIPTION of the news item (string) + * **title** - the TITLE of the news item (string) + * **org** - the ID of the org that owns this news item (int) + * **link** - the link to the source of this news item (string) + * **category** - the CATEGORY of of this news item (dictionary) + + Example: + + GET /api/v1/news/org/1/ + + Response is the list of news items of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/news/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "short_description": "This is a test news item that I want to use to test my api and speed of typing", + "title": "test", + "description": "This is a test news item that I want to use to test my api and speed of typing", + "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + """ + + serializer_class = NewsItemReadSerializer + model = NewsItem + + +class NewsItemDetails(RetrieveAPIView): + """ + This endpoint allows you to get a single news item + + ## A single news item + Example: + + GET /api/v1/news/1/ + + Response is a single news item: + + { + "id": 1, + "short_description": "This is a test news item that I want to use to test my api and speed of typing", + "title": "test", + "description": "This is a test news item that I want to use to test my api and speed of typing", + "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + } + """ + + serializer_class = NewsItemReadSerializer + queryset = NewsItem.objects.filter(is_active=True) + + +class VideoList(BaseListAPIView): + """ + This endpoint allows you to list videos. + + ## Listing videos + + By making a ```GET``` request you can list all the videos for an organization, filtering them as needed. Each + video has the following attributes: + + * **id** - the ID of the video (int) + * **description** - the DESCRIPTION of the video (string) + * **title** - the TITLE of the video (string) + * **org** - the ID of the org that owns this video (int) + * **link** - the link to the source of this news item (string) + * **category** - the CATEGORY of of this news item (dictionary) + + Example: + + GET /api/v1/videos/org/1/ + + Response is the list of videos of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/videos/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "title": "test", + "description": "This guy is hating on the benz", + "video_id": "ZPJ64sTa7KI", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + """ + + serializer_class = VideoReadSerializer + model = Video + + +class VideoDetails(RetrieveAPIView): + """ + This endpoint allows you to a single video + + ## A single Video + + Example: + + GET /api/v1/videos/1/ + + Response is a single Video: + + { + "id": 1, + "title": "test", + "description": "This guy is hating on the benz", + "video_id": "ZPJ64sTa7KI", + "org": 1, + "category": { + "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + } + """ + + serializer_class = VideoReadSerializer + queryset = Video.objects.filter(is_active=True) + + +class ImageList(BaseListAPIView): + """ + This endpoint allows you to list assets. + + ## Listing assets + + By making a ```GET``` request you can list all the assets for an organization, filtering them as needed. Each + asset has the following attributes: + + * **id** - the ID of the asset (int) + * **image_type** - the IMAGE_TYPE of the asset (string) + * **title** - the TITLE of the asset (string) + * **org** - the ID of the org that owns this asset (int) + * **name** - the name of the asset (string) + + Example: + + GET /api/v1/assets/org/1/ + + Response is the list of assets of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/assets/org/1/?page=2", + "previous": null, + "results": [ + { + "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", + "image_type": "B", + "org": 1, + "name": "Image name" + }, + ... + } + """ + + serializer_class = ImageReadSerializer + model = Image + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(is_active=True, image_type="L") + + +class ImageDetails(RetrieveAPIView): + """ + This endpoint allows you to a single assets. + + ## A single asset + + Example: + + GET /api/v1/assets/1/ + + Response is a single asset: + + { + "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", + "image_type": "B", + "org": 1, + "name": "Image name" + } + """ + + serializer_class = ImageReadSerializer + queryset = Image.objects.filter(is_active=True, image_type="L") + + +class StoryList(BaseListAPIView): + """ + This endpoint allows you to list stories. + + ## Listing stories + + By making a ```GET``` request you can list all the stories for an organization, filtering them as needed. Each + story has the following attributes: + + * **id** - the ID of the story (int) + * **title** - the TITLE of the story (string) + * **featured** - whether the story if FEATURED or not (boolean) + * **org** - the ID of the org that owns this story (int) + * **summary** - the summary of the story (string) + * **content** - the content of the story (string), this can be containing HTML code data as the content is managed as WYSIWYG + * **video_id** - YouTube ID of the video in this story (string) + * **audio_link** - the AUDIO_LINK in this story (string) + * **tags** - the TAGS in this story (string) + * **images** - the IMAGES in this story (list of strings) + * **category** - the CATEGORY of the asset (dictionary) + + Example: + + GET /api/v1/stories/org/1/ + + Response is the list of stories of the organisation, most recent first: + + { + "count": 389, + "next": "/api/v1/stories/org/1/?page=2", + "previous": null, + "results": [ + { + "id": 1, + "title": "Test Story", + "featured": true, + "summary": "This is the summary of the story.", + "content": "This is the content of the story.", + "video_id": "", + "audio_link": null, + "tags": " test, story ", + "org": 1, + "images": [ + "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", + "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "name": "tests" + } + }, + ... + } + + + 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 + model = Story + + +class StoryDetails(RetrieveAPIView): + """ + This endpoint allows you to a single story. + + ## A single story + + Example: + + GET /api/v1/stories/1/ + + Response is a single story: + + { + "id": 1, + "title": "Test Story", + "featured": true, + "summary": "This is the summary of the story.", + "content": "This is the content of the story.", + "video_id": "", + "audio_link": null, + "tags": " test, story ", + "org": 1, + "images": [ + "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", + "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" + ], + "category": { + "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", + "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 + queryset = Story.objects.filter(is_active=True).filter(Q(attachment="") | Q(attachment=None)) + + +class DashBlockList(BaseListAPIView): + """ + This endpoint allows you to list dashblocks. + + ## Listing dashblocks + + By making a ```GET``` request you can list all the dashblocks for an organization, filtering them as needed. Each + dashblock has the following attributes: + + * **id** - the ID of the story (int) + * **org** - the ID of the org that owns this dashblock (int) + * **dashblock_type** - the type of the dashblock (string) filterable as `dashblock_type`. + * **priority** - the priority of the dashblock (int) + * **title** - the title of the dashblock (string) + * **summary** - the summary of the dashblock (string) + * **content** - the content of the dashblock (string), this can be containing HTML code data as the content is managed as WYSIWYG + * **image_url** - the image url of the dashblock image (string) + * **color** - the color of the dashblock (string) + * **path** - the path of the dashblock to use after the root URL (string) + * **video_id** - the video_id of the dashblock image (string) + * **tags** - the tags of the dashblock (string) + + + Example: + + GET /api/v1/dashblocks/org/1/ + + Response is the list of dashblocks of the organisation + { + "count": 13, + "next": "http://test.ureport.in/api/v1/dashblocks/org/1/?limit=10&offset=10", + "previous": null, + "results": [ + { + "id": 12, + "org": 1, + "dashblock_type": "photos", + "priority": 1, + "title": "CRC@30", + "summary": null, + "content": "Happy Child", + "image_url": "http://test.ureport.in/media/cache/ac/a7/aca7e7ae228e107b9186e77f222faabe.jpg", + "color": null, + "path": null, + "video_id": null, + "tags": null + }, + { + "id": 54, + "org": 1, + "dashblock_type": "photos", + "priority": 0, + "title": "World Mental Day Poll", + "summary": null, + "content": "", + "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", + "color": null, + "link": null, + "video_id": null, + "tags": null + } + ] + } + + """ + + serializer_class = DashblockReadSerializer + model = DashBlock + exclusive_params = ("dashblock_type",) + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(is_active=True).select_related("dashblock_type") + + def filter_queryset(self, queryset): + params = self.request.query_params + + # filter by UUID (optional) + d_type = params.get("dashblock_type") + if d_type: + queryset = queryset.filter(dashblock_type__slug=d_type) + + return queryset + + +class DashBlockDetails(RetrieveAPIView): + """ + This endpoint allows you to a single dashblock. + + ## A single dashblock + + Example: + + GET /api/v1/dashblocks/1/ + + Response is a single dashblock: + + { + "id": 1, + "org": 1, + "dashblock_type": "about", + "priority": 0, + "title": "About", + "summary": "U-report is a free SMS social monitoring.", + "content": "U-report is a free SMS social monitoring tool for community participation, designed to address issues that the population cares about.", + "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", + "color": null, + "link": null, + "video_id": null, + "tags": null + }, + """ + + serializer_class = DashblockReadSerializer + model = DashBlock + queryset = DashBlock.objects.filter(is_active=True) diff --git a/ureport/api/views.py b/ureport/api/views.py index c8d48f495..6d158bcbc 100644 --- a/ureport/api/views.py +++ b/ureport/api/views.py @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 From ab2592072f72695f2532e37d2c89a37860be40c1 Mon Sep 17 00:00:00 2001 From: Redwan Hasif Alvi <95750048+alviriseup@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:18:23 +0600 Subject: [PATCH 3/9] Delete serializers_20220103184452.py --- .../ureport/api/serializers_20220103184452.py | 220 ------------------ 1 file changed, 220 deletions(-) delete mode 100644 .history/ureport/api/serializers_20220103184452.py diff --git a/.history/ureport/api/serializers_20220103184452.py b/.history/ureport/api/serializers_20220103184452.py deleted file mode 100644 index e6b684205..000000000 --- a/.history/ureport/api/serializers_20220103184452.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - -import json - -import six -from rest_framework import serializers -from rest_framework.fields import SerializerMethodField -from sorl.thumbnail import get_thumbnail - -from dash.categories.models import Category -from dash.dashblocks.models import DashBlock -from dash.orgs.models import Org -from dash.stories.models import Story -from ureport.assets.models import Image -from ureport.news.models import NewsItem, Video -from ureport.polls.models import Poll - - -def generate_absolute_url_from_file(request, file, thumbnail_geometry): - thumnail = get_thumbnail(file, thumbnail_geometry, crop="center", quality=99) - return request.build_absolute_uri(thumnail.url) - - -class CategoryReadSerializer(serializers.ModelSerializer): - image_url = SerializerMethodField() - - def get_image_url(self, obj): - image = None - if obj.image: - image = obj.image - elif obj.get_first_image(): - image = obj.get_first_image() - if image: - return generate_absolute_url_from_file(self.context["request"], image, "800x600") - return None - - class Meta: - model = Category - fields = ("image_url", "name") - - -class OrgReadSerializer(serializers.ModelSerializer): - logo_url = SerializerMethodField() - gender_stats = SerializerMethodField() - age_stats = SerializerMethodField() - registration_stats = SerializerMethodField() - occupation_stats = SerializerMethodField() - reporters_count = SerializerMethodField() - timezone = SerializerMethodField() - - class Meta: - model = Org - fields = ( - "id", - "logo_url", - "name", - "language", - "subdomain", - "domain", - "timezone", - "gender_stats", - "age_stats", - "registration_stats", - "occupation_stats", - "reporters_count", - ) - - def get_logo_url(self, obj): - if obj.get_logo(): - return generate_absolute_url_from_file(self.context["request"], obj.get_logo(), "x180") - return None - - def get_gender_stats(self, obj): - return obj.get_gender_stats() - - def get_age_stats(self, obj): - return json.loads(obj.get_age_stats()) - - def get_registration_stats(self, obj): - return json.loads(obj.get_registration_stats()) - - def get_occupation_stats(self, obj): - return json.loads(obj.get_occupation_stats()) - - def get_reporters_count(self, obj): - return obj.get_reporters_count() - - def get_timezone(self, obj): - return six.text_type(obj.timezone) - - -class StoryReadSerializer(serializers.ModelSerializer): - category = CategoryReadSerializer() - images = SerializerMethodField() - - def get_images(self, obj): - return [ - generate_absolute_url_from_file(self.context["request"], image.image, "800x600") - for image in obj.get_featured_images() - ] - - class Meta: - model = Story - fields = ( - "id", - "title", - "featured", - "summary", - "content", - "video_id", - "audio_link", - "tags", - "org", - "images", - "category", - "created_on", - ) - - -class PollReadSerializer(serializers.ModelSerializer): - category = CategoryReadSerializer() - questions = SerializerMethodField() - - def get_questions(self, obj): - questions = [] - for question in obj.get_questions(): - open_ended = question.is_open_ended() - results_dict = dict(open_ended=open_ended) - results = question.get_results() - if results: - results_dict = results[0] - results_by_age = question.get_results(segment=dict(age="Age")) - results_by_gender = question.get_results(segment=dict(gender="Gender")) - results_by_state = question.get_results(segment=dict(location="State")) - - question_data = { - "id": question.pk, - "ruleset_uuid": question.flow_result.result_uuid, - "title": question.title, - "results": results_dict, - } - - if not open_ended: - question_data["results_by_age"] = results_by_age - question_data["results_by_gender"] = results_by_gender - question_data["results_by_location"] = results_by_state - - questions.append(question_data) - - return questions - - class Meta: - model = Poll - fields = ("id", "flow_uuid", "title", "org", "category", "poll_date", "modified_on", "created_on", "questions") - - -class NewsItemReadSerializer(serializers.ModelSerializer): - short_description = SerializerMethodField() - category = CategoryReadSerializer() - - def get_short_description(self, obj): - return obj.short_description() - - class Meta: - model = NewsItem - fields = ("id", "short_description", "category", "title", "description", "link", "org", "created_on") - - -class VideoReadSerializer(serializers.ModelSerializer): - category = CategoryReadSerializer() - - class Meta: - model = Video - fields = ("id", "category", "title", "description", "video_id", "org", "created_on") - - -class ImageReadSerializer(serializers.ModelSerializer): - image_url = SerializerMethodField() - - def get_image_url(self, obj): - return generate_absolute_url_from_file(self.context["request"], obj.image, "x180") - - class Meta: - model = Image - fields = ("id", "image_url", "image_type", "org", "name", "created_on") - - -class DashblockReadSerializer(serializers.ModelSerializer): - dashblock_type = SerializerMethodField() - image_url = SerializerMethodField() - path = SerializerMethodField() - - def get_image_url(self, obj): - if obj.image: - return generate_absolute_url_from_file(self.context["request"], obj.image, "800x600") - return None - - def get_dashblock_type(self, obj): - return obj.dashblock_type.slug - - def get_path(self, obj): - return obj.link - - class Meta: - model = DashBlock - fields = ( - "id", - "org", - "dashblock_type", - "priority", - "title", - "summary", - "content", - "image_url", - "color", - "path", - "video_id", - "tags", - ) From 8561e8420c54159abb76fa1b022ba79ec21970d2 Mon Sep 17 00:00:00 2001 From: Redwan Hasif Alvi <95750048+alviriseup@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:18:44 +0600 Subject: [PATCH 4/9] Delete serializers_20220103185012.py --- .../ureport/api/serializers_20220103185012.py | 271 ------------------ 1 file changed, 271 deletions(-) delete mode 100644 .history/ureport/api/serializers_20220103185012.py diff --git a/.history/ureport/api/serializers_20220103185012.py b/.history/ureport/api/serializers_20220103185012.py deleted file mode 100644 index a8f134914..000000000 --- a/.history/ureport/api/serializers_20220103185012.py +++ /dev/null @@ -1,271 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - -import json - -import six -from rest_framework import serializers -from rest_framework.fields import SerializerMethodField -from sorl.thumbnail import get_thumbnail - -from dash.categories.models import Category -from dash.dashblocks.models import DashBlock -from dash.orgs.models import Org -from dash.stories.models import Story -from ureport.assets.models import Image -from ureport.news.models import NewsItem, Video -from ureport.polls.models import Poll - - -def generate_absolute_url_from_file(request, file, thumbnail_geometry): - thumnail = get_thumbnail(file, thumbnail_geometry, crop="center", quality=99) - return request.build_absolute_uri(thumnail.url) - - -class CategoryReadSerializer(serializers.ModelSerializer): - image_url = SerializerMethodField() - - def get_image_url(self, obj): - image = None - if obj.image: - image = obj.image - elif obj.get_first_image(): - image = obj.get_first_image() - if image: - return generate_absolute_url_from_file(self.context["request"], image, "800x600") - return None - - class Meta: - model = Category - fields = ("image_url", "name") - - -class OrgReadSerializer(serializers.ModelSerializer): - logo_url = SerializerMethodField() - gender_stats = SerializerMethodField() - age_stats = SerializerMethodField() - registration_stats = SerializerMethodField() - occupation_stats = SerializerMethodField() - reporters_count = SerializerMethodField() - timezone = SerializerMethodField() - - class Meta: - model = Org - fields = ( - "id", - "logo_url", - "name", - "language", - "subdomain", - "domain", - "timezone", - "gender_stats", - "age_stats", - "registration_stats", - "occupation_stats", - "reporters_count", - ) - - def get_logo_url(self, obj): - if obj.get_logo(): - return generate_absolute_url_from_file(self.context["request"], obj.get_logo(), "x180") - return None - - def get_gender_stats(self, obj): - return obj.get_gender_stats() - - def get_age_stats(self, obj): - return json.loads(obj.get_age_stats()) - - def get_registration_stats(self, obj): - return json.loads(obj.get_registration_stats()) - - def get_occupation_stats(self, obj): - return json.loads(obj.get_occupation_stats()) - - def get_reporters_count(self, obj): - return obj.get_reporters_count() - - def get_timezone(self, obj): - return six.text_type(obj.timezone) - - -class StoryReadSerializer(serializers.ModelSerializer): - category = CategoryReadSerializer() - images = SerializerMethodField() - - def get_images(self, obj): - return [ - generate_absolute_url_from_file(self.context["request"], image.image, "800x600") - for image in obj.get_featured_images() - ] - - # Function to use ?fields and ?exclude API calls for specific attributes in stories - # this is for which we can exclude any field - def __init__(self, *args, **kwargs): - # Don't pass the 'fields' arg up to the superclass - request = kwargs.get('context', {}).get('request') - str_fields = request.GET.get('exclude', '') if request else None - str_exclude_fields = request.GET.get('fields', '') if request else None - exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None - fields = str_fields.split(',') if str_fields else None - - # Instantiate the superclass normally - super(StoryReadSerializer, self).__init__(*args, **kwargs) - - if fields is not None: - # Drop any fields that are not specified in the `fields` argument. - allowed = set(fields) - existing = set(self.fields) - for field_name in allowed: - self.fields.pop(field_name) - elif exclude_fields is not None: - allowed_fields = set(exclude_fields) - existing_data = set(self.fields) - for field_names in existing_data - allowed_fields: - self.fields.pop(field_names) - - - class Meta: - model = Story - fields = ( - "id", - "title", - "featured", - "summary", - "content", - "video_id", - "audio_link", - "tags", - "org", - "images", - "category", - "created_on", - ) - - -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_fields = request.GET.get('exclude', '') if request else None - str_exclude_fields = request.GET.get('fields', '') if request else None - exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None - fields = str_fields.split(',') if str_fields else None - - # Instantiate the superclass normally - super(PollReadSerializer, self).__init__(*args, **kwargs) - - if fields is not None: - # Drop any fields that are not specified in the `fields` argument. - allowed = set(fields) - print('allowed :',allowed) - existing = set(self.fields) - for field_name in allowed: - self.fields.pop(field_name) - elif exclude_fields is not None: - allowed_fields = set(exclude_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(): - open_ended = question.is_open_ended() - results_dict = dict(open_ended=open_ended) - results = question.get_results() - if results: - results_dict = results[0] - results_by_age = question.get_results(segment=dict(age="Age")) - results_by_gender = question.get_results(segment=dict(gender="Gender")) - results_by_state = question.get_results(segment=dict(location="State")) - - question_data = { - "id": question.pk, - "ruleset_uuid": question.flow_result.result_uuid, - "title": question.title, - "results": results_dict, - } - - if not open_ended: - question_data["results_by_age"] = results_by_age - question_data["results_by_gender"] = results_by_gender - question_data["results_by_location"] = results_by_state - - questions.append(question_data) - - return questions - - class Meta: - model = Poll - fields = ("id", "flow_uuid", "title", "org", "category", "poll_date", "modified_on", "created_on", "questions") - - -class NewsItemReadSerializer(serializers.ModelSerializer): - short_description = SerializerMethodField() - category = CategoryReadSerializer() - - def get_short_description(self, obj): - return obj.short_description() - - class Meta: - model = NewsItem - fields = ("id", "short_description", "category", "title", "description", "link", "org", "created_on") - - -class VideoReadSerializer(serializers.ModelSerializer): - category = CategoryReadSerializer() - - class Meta: - model = Video - fields = ("id", "category", "title", "description", "video_id", "org", "created_on") - - -class ImageReadSerializer(serializers.ModelSerializer): - image_url = SerializerMethodField() - - def get_image_url(self, obj): - return generate_absolute_url_from_file(self.context["request"], obj.image, "x180") - - class Meta: - model = Image - fields = ("id", "image_url", "image_type", "org", "name", "created_on") - - -class DashblockReadSerializer(serializers.ModelSerializer): - dashblock_type = SerializerMethodField() - image_url = SerializerMethodField() - path = SerializerMethodField() - - def get_image_url(self, obj): - if obj.image: - return generate_absolute_url_from_file(self.context["request"], obj.image, "800x600") - return None - - def get_dashblock_type(self, obj): - return obj.dashblock_type.slug - - def get_path(self, obj): - return obj.link - - class Meta: - model = DashBlock - fields = ( - "id", - "org", - "dashblock_type", - "priority", - "title", - "summary", - "content", - "image_url", - "color", - "path", - "video_id", - "tags", - ) From 9f5fd6358df13ee2508a557c424f187d2ee09601 Mon Sep 17 00:00:00 2001 From: Redwan Hasif Alvi <95750048+alviriseup@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:18:52 +0600 Subject: [PATCH 5/9] Delete views_20220103184452.py --- .history/ureport/api/views_20220103184452.py | 990 ------------------- 1 file changed, 990 deletions(-) delete mode 100644 .history/ureport/api/views_20220103184452.py diff --git a/.history/ureport/api/views_20220103184452.py b/.history/ureport/api/views_20220103184452.py deleted file mode 100644 index c8d48f495..000000000 --- a/.history/ureport/api/views_20220103184452.py +++ /dev/null @@ -1,990 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - -from rest_framework.generics import ListAPIView, RetrieveAPIView - -from django.db.models import Q - -from dash.dashblocks.models import DashBlock -from dash.orgs.models import Org -from dash.stories.models import Story -from ureport.api.serializers import ( - DashblockReadSerializer, - ImageReadSerializer, - NewsItemReadSerializer, - OrgReadSerializer, - PollReadSerializer, - StoryReadSerializer, - VideoReadSerializer, -) -from ureport.assets.models import Image -from ureport.news.models import NewsItem, Video -from ureport.polls.models import Poll - - -class OrgList(ListAPIView): - """ - This endpoint allows you to list orgs. - - ## Listing Orgs - - By making a ```GET``` request you can list all the organisations. Each org has the following attributes: - - * **id** - the ID of the org (int) - * **logo_url** - the LOGO_URL of the org (string) - * **name** - the NAME of the org (string) - * **language** - the LANGUAGE of the org (string) - * **subdomain** - the SUBDOMAIN of of this org (string) - * **domain** - the DOMAIN of of this org (string) - * **timezone** - the TIMEZONE of of this org (string) - - Example: - - GET /api/v1/orgs/ - - Response is the list of orgs: - - { - "count": 389, - "next": "/api/v1/polls/orgs/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", - "name": "test", - "language": "en", - "subdomain": "test", - "domain": "ureport.in", - "timezone": "Africa/Kampala" - "gender_stats": { - "female_count": 0, - "male_percentage": "---", - "female_percentage": "---", - "male_count": 0 - }, - "age_stats": [], - "registration_stats": [{"count": 0, "label": "07/06/15"}], - "occupation_stats": [] - }, - ... - } - """ - - serializer_class = OrgReadSerializer - queryset = Org.objects.filter(is_active=True) - - -class OrgDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single org. - - ## Get a single org - - Example: - - GET /api/v1/orgs/1/ - - Response is a single org with that ID: - - { - "id": 1, - "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", - "name": "test", - "language": "en", - "subdomain": "test", - "domain": "ureport.in", - "timezone": "Africa/Kampala" - "gender_stats": { - "female_count": 0, - "male_percentage": "---", - "female_percentage": "---", - "male_count": 0 - }, - "age_stats": [], - "registration_stats": [{"count": 0, "label": "07/06/15"}], - "occupation_stats": [] - } - """ - - serializer_class = OrgReadSerializer - queryset = Org.objects.filter(is_active=True) - - -class BaseListAPIView(ListAPIView): - def get_queryset(self): - q = self.model.objects.filter(is_active=True).order_by("-created_on") - if self.kwargs.get("org", None): - q = q.filter(org_id=self.kwargs.get("org")) - return q - - -class PollList(BaseListAPIView): - """ - This endpoint allows you to list polls. - - ## Listing Polls - - By making a ```GET``` request you can list all the polls for an organization, filtering them as needed. Each - poll has the following attributes: - - * **id** - the ID of the poll (int) - * **flow_uuid** - the FLOW_UUID of the run (string) (filterable: ```flow_uuid```) - * **title** - the TITLE of the poll (string) - * **org** - the ID of the org that owns this poll (int) - * **category** - the CATEGORIES of of this poll (dictionary) - - * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` - - Example: - - GET /api/v1/polls/org/1/ - - Response is the list of polls, most recent first: - - { - "count": 389, - "next": "/api/v1/polls/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "category": { - "image_url": null, - "name": "Education" - }, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - - - - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - - ] - - - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "poll_date": "2015-09-02T08:53:30.313251Z", - "modified_on": "2015-09-02T08:53:30.313251Z", - "created_on": "2015-09-02T08:53:30.313251Z" - } - ... - ] - } - """ - - serializer_class = PollReadSerializer - model = Poll - - def get_queryset(self): - q = super(PollList, self).get_queryset() - q = q.filter(is_active=True, has_synced=True).exclude(flow_uuid="") - if self.request.query_params.get("flow_uuid", None): - q = q.filter(flow_uuid=self.request.query_params.get("flow_uuid")) - - if self.request.query_params.get("sort", None) == "modified_on": - q = q.order_by("-modified_on") - - return q - - -class PollDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single poll. - - ## Get a single poll - - Example: - - GET /api/v1/polls/1/ - - Response is a single poll with that ID: - - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "category": { - "image_url": null, - "name": "Education" - }, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "created_on": "2015-09-02T08:53:30.313251Z" - } - """ - - serializer_class = PollReadSerializer - queryset = Poll.objects.filter(is_active=True, has_synced=True).exclude(flow_uuid="") - - -class FeaturedPollList(BaseListAPIView): - """ - This endpoint allows you to list all featured polls for an organisation. - - ## Listing Featured Polls - - * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` - - Example: - - GET /api/v1/polls/org/1/featured/ - - Response is a list of the featured polls, most recent first. \ - An empty list is returned if there are no polls with questions. - - { - "count": 389, - "next": "/api/v1/polls/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - - - - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - - ] - - - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "poll_date": "2015-09-02T08:53:30.313251Z", - "modified_on": "2015-09-02T08:53:30.313251Z", - "created_on": "2015-09-02T08:53:30.313251Z" - } - ... - ] - } - """ - - serializer_class = PollReadSerializer - model = Poll - - def get_queryset(self): - q = super(FeaturedPollList, self).get_queryset() - - if self.request.query_params.get("sort", None) == "modified_on": - q = ( - q.filter(is_active=True, has_synced=True) - .exclude(flow_uuid="") - .filter(is_featured=True) - .order_by("-modified_on") - ) - else: - q = ( - q.filter(is_active=True, has_synced=True) - .exclude(flow_uuid="") - .filter(is_featured=True) - .order_by("-created_on") - ) - return q - - -class NewsItemList(BaseListAPIView): - """ - This endpoint allows you to list news items. - - ## Listing news items - - By making a ```GET``` request you can list all the news items for an organization, filtering them as needed. Each - news item has the following attributes: - - * **id** - the ID of the item (int) - * **short_description** - the SHORT_DESCRIPTION of the news item (string) - * **title** - the TITLE of the news item (string) - * **org** - the ID of the org that owns this news item (int) - * **link** - the link to the source of this news item (string) - * **category** - the CATEGORY of of this news item (dictionary) - - Example: - - GET /api/v1/news/org/1/ - - Response is the list of news items of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/news/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "short_description": "This is a test news item that I want to use to test my api and speed of typing", - "title": "test", - "description": "This is a test news item that I want to use to test my api and speed of typing", - "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - """ - - serializer_class = NewsItemReadSerializer - model = NewsItem - - -class NewsItemDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single news item - - ## A single news item - Example: - - GET /api/v1/news/1/ - - Response is a single news item: - - { - "id": 1, - "short_description": "This is a test news item that I want to use to test my api and speed of typing", - "title": "test", - "description": "This is a test news item that I want to use to test my api and speed of typing", - "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - } - """ - - serializer_class = NewsItemReadSerializer - queryset = NewsItem.objects.filter(is_active=True) - - -class VideoList(BaseListAPIView): - """ - This endpoint allows you to list videos. - - ## Listing videos - - By making a ```GET``` request you can list all the videos for an organization, filtering them as needed. Each - video has the following attributes: - - * **id** - the ID of the video (int) - * **description** - the DESCRIPTION of the video (string) - * **title** - the TITLE of the video (string) - * **org** - the ID of the org that owns this video (int) - * **link** - the link to the source of this news item (string) - * **category** - the CATEGORY of of this news item (dictionary) - - Example: - - GET /api/v1/videos/org/1/ - - Response is the list of videos of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/videos/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "title": "test", - "description": "This guy is hating on the benz", - "video_id": "ZPJ64sTa7KI", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - """ - - serializer_class = VideoReadSerializer - model = Video - - -class VideoDetails(RetrieveAPIView): - """ - This endpoint allows you to a single video - - ## A single Video - - Example: - - GET /api/v1/videos/1/ - - Response is a single Video: - - { - "id": 1, - "title": "test", - "description": "This guy is hating on the benz", - "video_id": "ZPJ64sTa7KI", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - } - """ - - serializer_class = VideoReadSerializer - queryset = Video.objects.filter(is_active=True) - - -class ImageList(BaseListAPIView): - """ - This endpoint allows you to list assets. - - ## Listing assets - - By making a ```GET``` request you can list all the assets for an organization, filtering them as needed. Each - asset has the following attributes: - - * **id** - the ID of the asset (int) - * **image_type** - the IMAGE_TYPE of the asset (string) - * **title** - the TITLE of the asset (string) - * **org** - the ID of the org that owns this asset (int) - * **name** - the name of the asset (string) - - Example: - - GET /api/v1/assets/org/1/ - - Response is the list of assets of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/assets/org/1/?page=2", - "previous": null, - "results": [ - { - "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", - "image_type": "B", - "org": 1, - "name": "Image name" - }, - ... - } - """ - - serializer_class = ImageReadSerializer - model = Image - - def get_queryset(self): - queryset = super().get_queryset() - return queryset.filter(is_active=True, image_type="L") - - -class ImageDetails(RetrieveAPIView): - """ - This endpoint allows you to a single assets. - - ## A single asset - - Example: - - GET /api/v1/assets/1/ - - Response is a single asset: - - { - "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", - "image_type": "B", - "org": 1, - "name": "Image name" - } - """ - - serializer_class = ImageReadSerializer - queryset = Image.objects.filter(is_active=True, image_type="L") - - -class StoryList(BaseListAPIView): - """ - This endpoint allows you to list stories. - - ## Listing stories - - By making a ```GET``` request you can list all the stories for an organization, filtering them as needed. Each - story has the following attributes: - - * **id** - the ID of the story (int) - * **title** - the TITLE of the story (string) - * **featured** - whether the story if FEATURED or not (boolean) - * **org** - the ID of the org that owns this story (int) - * **summary** - the summary of the story (string) - * **content** - the content of the story (string), this can be containing HTML code data as the content is managed as WYSIWYG - * **video_id** - YouTube ID of the video in this story (string) - * **audio_link** - the AUDIO_LINK in this story (string) - * **tags** - the TAGS in this story (string) - * **images** - the IMAGES in this story (list of strings) - * **category** - the CATEGORY of the asset (dictionary) - - Example: - - GET /api/v1/stories/org/1/ - - Response is the list of stories of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/stories/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "title": "Test Story", - "featured": true, - "summary": "This is the summary of the story.", - "content": "This is the content of the story.", - "video_id": "", - "audio_link": null, - "tags": " test, story ", - "org": 1, - "images": [ - "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", - "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - """ - - serializer_class = StoryReadSerializer - model = Story - - -class StoryDetails(RetrieveAPIView): - """ - This endpoint allows you to a single story. - - ## A single story - - Example: - - GET /api/v1/stories/1/ - - Response is a single story: - - { - "id": 1, - "title": "Test Story", - "featured": true, - "summary": "This is the summary of the story.", - "content": "This is the content of the story.", - "video_id": "", - "audio_link": null, - "tags": " test, story ", - "org": 1, - "images": [ - "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", - "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - } - """ - - serializer_class = StoryReadSerializer - queryset = Story.objects.filter(is_active=True).filter(Q(attachment="") | Q(attachment=None)) - - -class DashBlockList(BaseListAPIView): - """ - This endpoint allows you to list dashblocks. - - ## Listing dashblocks - - By making a ```GET``` request you can list all the dashblocks for an organization, filtering them as needed. Each - dashblock has the following attributes: - - * **id** - the ID of the story (int) - * **org** - the ID of the org that owns this dashblock (int) - * **dashblock_type** - the type of the dashblock (string) filterable as `dashblock_type`. - * **priority** - the priority of the dashblock (int) - * **title** - the title of the dashblock (string) - * **summary** - the summary of the dashblock (string) - * **content** - the content of the dashblock (string), this can be containing HTML code data as the content is managed as WYSIWYG - * **image_url** - the image url of the dashblock image (string) - * **color** - the color of the dashblock (string) - * **path** - the path of the dashblock to use after the root URL (string) - * **video_id** - the video_id of the dashblock image (string) - * **tags** - the tags of the dashblock (string) - - - Example: - - GET /api/v1/dashblocks/org/1/ - - Response is the list of dashblocks of the organisation - { - "count": 13, - "next": "http://test.ureport.in/api/v1/dashblocks/org/1/?limit=10&offset=10", - "previous": null, - "results": [ - { - "id": 12, - "org": 1, - "dashblock_type": "photos", - "priority": 1, - "title": "CRC@30", - "summary": null, - "content": "Happy Child", - "image_url": "http://test.ureport.in/media/cache/ac/a7/aca7e7ae228e107b9186e77f222faabe.jpg", - "color": null, - "path": null, - "video_id": null, - "tags": null - }, - { - "id": 54, - "org": 1, - "dashblock_type": "photos", - "priority": 0, - "title": "World Mental Day Poll", - "summary": null, - "content": "", - "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", - "color": null, - "link": null, - "video_id": null, - "tags": null - } - ] - } - - """ - - serializer_class = DashblockReadSerializer - model = DashBlock - exclusive_params = ("dashblock_type",) - - def get_queryset(self): - queryset = super().get_queryset() - return queryset.filter(is_active=True).select_related("dashblock_type") - - def filter_queryset(self, queryset): - params = self.request.query_params - - # filter by UUID (optional) - d_type = params.get("dashblock_type") - if d_type: - queryset = queryset.filter(dashblock_type__slug=d_type) - - return queryset - - -class DashBlockDetails(RetrieveAPIView): - """ - This endpoint allows you to a single dashblock. - - ## A single dashblock - - Example: - - GET /api/v1/dashblocks/1/ - - Response is a single dashblock: - - { - "id": 1, - "org": 1, - "dashblock_type": "about", - "priority": 0, - "title": "About", - "summary": "U-report is a free SMS social monitoring.", - "content": "U-report is a free SMS social monitoring tool for community participation, designed to address issues that the population cares about.", - "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", - "color": null, - "link": null, - "video_id": null, - "tags": null - }, - """ - - serializer_class = DashblockReadSerializer - model = DashBlock - queryset = DashBlock.objects.filter(is_active=True) From 6c86b4d9fc4ca62986e2922e4894d5d6d3283c93 Mon Sep 17 00:00:00 2001 From: Redwan Hasif Alvi <95750048+alviriseup@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:19:01 +0600 Subject: [PATCH 6/9] Delete views_20220103190914.py --- .history/ureport/api/views_20220103190914.py | 1089 ------------------ 1 file changed, 1089 deletions(-) delete mode 100644 .history/ureport/api/views_20220103190914.py diff --git a/.history/ureport/api/views_20220103190914.py b/.history/ureport/api/views_20220103190914.py deleted file mode 100644 index 6d158bcbc..000000000 --- a/.history/ureport/api/views_20220103190914.py +++ /dev/null @@ -1,1089 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - -from rest_framework.generics import ListAPIView, RetrieveAPIView - -from django.db.models import Q - -from dash.dashblocks.models import DashBlock -from dash.orgs.models import Org -from dash.stories.models import Story -from ureport.api.serializers import ( - DashblockReadSerializer, - ImageReadSerializer, - NewsItemReadSerializer, - OrgReadSerializer, - PollReadSerializer, - StoryReadSerializer, - VideoReadSerializer, -) -from ureport.assets.models import Image -from ureport.news.models import NewsItem, Video -from ureport.polls.models import Poll - - -class OrgList(ListAPIView): - """ - This endpoint allows you to list orgs. - - ## Listing Orgs - - By making a ```GET``` request you can list all the organisations. Each org has the following attributes: - - * **id** - the ID of the org (int) - * **logo_url** - the LOGO_URL of the org (string) - * **name** - the NAME of the org (string) - * **language** - the LANGUAGE of the org (string) - * **subdomain** - the SUBDOMAIN of of this org (string) - * **domain** - the DOMAIN of of this org (string) - * **timezone** - the TIMEZONE of of this org (string) - - Example: - - GET /api/v1/orgs/ - - Response is the list of orgs: - - { - "count": 389, - "next": "/api/v1/polls/orgs/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", - "name": "test", - "language": "en", - "subdomain": "test", - "domain": "ureport.in", - "timezone": "Africa/Kampala" - "gender_stats": { - "female_count": 0, - "male_percentage": "---", - "female_percentage": "---", - "male_count": 0 - }, - "age_stats": [], - "registration_stats": [{"count": 0, "label": "07/06/15"}], - "occupation_stats": [] - }, - ... - } - """ - - serializer_class = OrgReadSerializer - queryset = Org.objects.filter(is_active=True) - - -class OrgDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single org. - - ## Get a single org - - Example: - - GET /api/v1/orgs/1/ - - Response is a single org with that ID: - - { - "id": 1, - "logo_url": "http://test.ureport.in/media/logos/StraightOuttaSomewhere_2.jpg", - "name": "test", - "language": "en", - "subdomain": "test", - "domain": "ureport.in", - "timezone": "Africa/Kampala" - "gender_stats": { - "female_count": 0, - "male_percentage": "---", - "female_percentage": "---", - "male_count": 0 - }, - "age_stats": [], - "registration_stats": [{"count": 0, "label": "07/06/15"}], - "occupation_stats": [] - } - """ - - serializer_class = OrgReadSerializer - queryset = Org.objects.filter(is_active=True) - - -class BaseListAPIView(ListAPIView): - def get_queryset(self): - q = self.model.objects.filter(is_active=True).order_by("-created_on") - if self.kwargs.get("org", None): - q = q.filter(org_id=self.kwargs.get("org")) - return q - - -class PollList(BaseListAPIView): - """ - This endpoint allows you to list polls. - - ## Listing Polls - - By making a ```GET``` request you can list all the polls for an organization, filtering them as needed. Each - poll has the following attributes: - - * **id** - the ID of the poll (int) - * **flow_uuid** - the FLOW_UUID of the run (string) (filterable: ```flow_uuid```) - * **title** - the TITLE of the poll (string) - * **org** - the ID of the org that owns this poll (int) - * **category** - the CATEGORIES of of this poll (dictionary) - - * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` - - Example: - - GET /api/v1/polls/org/1/ - - Response is the list of polls, most recent first: - - { - "count": 389, - "next": "/api/v1/polls/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "category": { - "image_url": null, - "name": "Education" - }, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - - - - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - - ] - - - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "poll_date": "2015-09-02T08:53:30.313251Z", - "modified_on": "2015-09-02T08:53:30.313251Z", - "created_on": "2015-09-02T08:53:30.313251Z" - } - ... - ] - } - - - 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 - model = Poll - - def get_queryset(self): - q = super(PollList, self).get_queryset() - q = q.filter(is_active=True, has_synced=True).exclude(flow_uuid="") - if self.request.query_params.get("flow_uuid", None): - q = q.filter(flow_uuid=self.request.query_params.get("flow_uuid")) - - if self.request.query_params.get("sort", None) == "modified_on": - q = q.order_by("-modified_on") - - return q - - -class PollDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single poll. - - ## Get a single poll - - Example: - - GET /api/v1/polls/1/ - - Response is a single poll with that ID: - - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "category": { - "image_url": null, - "name": "Education" - }, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "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 - queryset = Poll.objects.filter(is_active=True, has_synced=True).exclude(flow_uuid="") - - -class FeaturedPollList(BaseListAPIView): - """ - This endpoint allows you to list all featured polls for an organisation. - - ## Listing Featured Polls - - * **sort** - Order the results by modified on desceding if specified and equal to ```modified_on``` - - Example: - - GET /api/v1/polls/org/1/featured/ - - Response is a list of the featured polls, most recent first. \ - An empty list is returned if there are no polls with questions. - - { - "count": 389, - "next": "/api/v1/polls/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 2, - "flow_uuid": "a497ba0f-6b58-4bed-ba52-05c3f40403e2", - "title": "Food Poll", - "org": 1, - "questions": [ - { - "id": 14, - "title": "Are you hungry?", - "ruleset_uuid": "ea74b2c2-7425-443a-97cb-331d4e11abb6", - "results": - { - "open_ended": false, - "set": 100, - "unset": 150, - "categories": [ - { - "count": 60, - "label": "Yes" - }, - { - "count": 30, - "label": "NO" - }, - { - "count": 10, - "label": "Thirsty" - }, - { - "count": 0, - "label": "Other" - }, - ] - } - }, - { - - - - "id": 16, - "title": "What would you like to eat", - "ruleset_uuid": "66e08f93-cdff-4dbc-bd02-c746770a4fac", - "results": - { - "open_ended": true, - "set": 70, - "unset": 30, - "categories": [ - { - "count": 40, - "label": "Food" - }, - { - "count": 10, - "label": "Cake" - }, - { - "count": 15, - "label": "Fruits" - }, - { - "count": 5, - "label": "Coffee" - }, - ] - } - }, - { - "id": 17, - "title": "Where would you like to eat?", - "ruleset_uuid": "e31755dd-c61a-460c-acaf-0eeee1ce0107", - "results": - { - "open_ended": false, - "set": 50, - "unset": 20, - "categories": [ - { - "count": 30, - "label": "Home" - }, - { - "count": 12, - "label": "Resto" - }, - { - "count": 5, - "label": "Fast Food" - }, - { - "count": 3, - "label": "Other" - }, - ] - } - } - - ] - - - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - }, - "poll_date": "2015-09-02T08:53:30.313251Z", - "modified_on": "2015-09-02T08:53:30.313251Z", - "created_on": "2015-09-02T08:53:30.313251Z" - } - ... - ] - } - - - 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 - model = Poll - - def get_queryset(self): - q = super(FeaturedPollList, self).get_queryset() - - if self.request.query_params.get("sort", None) == "modified_on": - q = ( - q.filter(is_active=True, has_synced=True) - .exclude(flow_uuid="") - .filter(is_featured=True) - .order_by("-modified_on") - ) - else: - q = ( - q.filter(is_active=True, has_synced=True) - .exclude(flow_uuid="") - .filter(is_featured=True) - .order_by("-created_on") - ) - return q - - -class NewsItemList(BaseListAPIView): - """ - This endpoint allows you to list news items. - - ## Listing news items - - By making a ```GET``` request you can list all the news items for an organization, filtering them as needed. Each - news item has the following attributes: - - * **id** - the ID of the item (int) - * **short_description** - the SHORT_DESCRIPTION of the news item (string) - * **title** - the TITLE of the news item (string) - * **org** - the ID of the org that owns this news item (int) - * **link** - the link to the source of this news item (string) - * **category** - the CATEGORY of of this news item (dictionary) - - Example: - - GET /api/v1/news/org/1/ - - Response is the list of news items of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/news/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "short_description": "This is a test news item that I want to use to test my api and speed of typing", - "title": "test", - "description": "This is a test news item that I want to use to test my api and speed of typing", - "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - """ - - serializer_class = NewsItemReadSerializer - model = NewsItem - - -class NewsItemDetails(RetrieveAPIView): - """ - This endpoint allows you to get a single news item - - ## A single news item - Example: - - GET /api/v1/news/1/ - - Response is a single news item: - - { - "id": 1, - "short_description": "This is a test news item that I want to use to test my api and speed of typing", - "title": "test", - "description": "This is a test news item that I want to use to test my api and speed of typing", - "link": "http://stackoverflow.com/questions/3876977/update-git-branches-from-master", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - } - """ - - serializer_class = NewsItemReadSerializer - queryset = NewsItem.objects.filter(is_active=True) - - -class VideoList(BaseListAPIView): - """ - This endpoint allows you to list videos. - - ## Listing videos - - By making a ```GET``` request you can list all the videos for an organization, filtering them as needed. Each - video has the following attributes: - - * **id** - the ID of the video (int) - * **description** - the DESCRIPTION of the video (string) - * **title** - the TITLE of the video (string) - * **org** - the ID of the org that owns this video (int) - * **link** - the link to the source of this news item (string) - * **category** - the CATEGORY of of this news item (dictionary) - - Example: - - GET /api/v1/videos/org/1/ - - Response is the list of videos of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/videos/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "title": "test", - "description": "This guy is hating on the benz", - "video_id": "ZPJ64sTa7KI", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - """ - - serializer_class = VideoReadSerializer - model = Video - - -class VideoDetails(RetrieveAPIView): - """ - This endpoint allows you to a single video - - ## A single Video - - Example: - - GET /api/v1/videos/1/ - - Response is a single Video: - - { - "id": 1, - "title": "test", - "description": "This guy is hating on the benz", - "video_id": "ZPJ64sTa7KI", - "org": 1, - "category": { - "image_url": "http://fake.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - } - """ - - serializer_class = VideoReadSerializer - queryset = Video.objects.filter(is_active=True) - - -class ImageList(BaseListAPIView): - """ - This endpoint allows you to list assets. - - ## Listing assets - - By making a ```GET``` request you can list all the assets for an organization, filtering them as needed. Each - asset has the following attributes: - - * **id** - the ID of the asset (int) - * **image_type** - the IMAGE_TYPE of the asset (string) - * **title** - the TITLE of the asset (string) - * **org** - the ID of the org that owns this asset (int) - * **name** - the name of the asset (string) - - Example: - - GET /api/v1/assets/org/1/ - - Response is the list of assets of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/assets/org/1/?page=2", - "previous": null, - "results": [ - { - "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", - "image_type": "B", - "org": 1, - "name": "Image name" - }, - ... - } - """ - - serializer_class = ImageReadSerializer - model = Image - - def get_queryset(self): - queryset = super().get_queryset() - return queryset.filter(is_active=True, image_type="L") - - -class ImageDetails(RetrieveAPIView): - """ - This endpoint allows you to a single assets. - - ## A single asset - - Example: - - GET /api/v1/assets/1/ - - Response is a single asset: - - { - "image_url": "http://test.ureport.in/media/images/Ai5BfWh79w7U8CN7jyiqOwn7S4F5gsUaFScdrRtf9-1o.jpg", - "image_type": "B", - "org": 1, - "name": "Image name" - } - """ - - serializer_class = ImageReadSerializer - queryset = Image.objects.filter(is_active=True, image_type="L") - - -class StoryList(BaseListAPIView): - """ - This endpoint allows you to list stories. - - ## Listing stories - - By making a ```GET``` request you can list all the stories for an organization, filtering them as needed. Each - story has the following attributes: - - * **id** - the ID of the story (int) - * **title** - the TITLE of the story (string) - * **featured** - whether the story if FEATURED or not (boolean) - * **org** - the ID of the org that owns this story (int) - * **summary** - the summary of the story (string) - * **content** - the content of the story (string), this can be containing HTML code data as the content is managed as WYSIWYG - * **video_id** - YouTube ID of the video in this story (string) - * **audio_link** - the AUDIO_LINK in this story (string) - * **tags** - the TAGS in this story (string) - * **images** - the IMAGES in this story (list of strings) - * **category** - the CATEGORY of the asset (dictionary) - - Example: - - GET /api/v1/stories/org/1/ - - Response is the list of stories of the organisation, most recent first: - - { - "count": 389, - "next": "/api/v1/stories/org/1/?page=2", - "previous": null, - "results": [ - { - "id": 1, - "title": "Test Story", - "featured": true, - "summary": "This is the summary of the story.", - "content": "This is the content of the story.", - "video_id": "", - "audio_link": null, - "tags": " test, story ", - "org": 1, - "images": [ - "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", - "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "name": "tests" - } - }, - ... - } - - - 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 - model = Story - - -class StoryDetails(RetrieveAPIView): - """ - This endpoint allows you to a single story. - - ## A single story - - Example: - - GET /api/v1/stories/1/ - - Response is a single story: - - { - "id": 1, - "title": "Test Story", - "featured": true, - "summary": "This is the summary of the story.", - "content": "This is the content of the story.", - "video_id": "", - "audio_link": null, - "tags": " test, story ", - "org": 1, - "images": [ - "http://test.ureport.in/media/stories/StraightOuttaSomewhere_1.jpg", - "http://test.ureport.in/media/stories/StraightOuttaSomewhere.jpg" - ], - "category": { - "image_url": "http://test.ureport.in/media/categories/StraightOuttaSomewhere_2.jpg", - "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 - queryset = Story.objects.filter(is_active=True).filter(Q(attachment="") | Q(attachment=None)) - - -class DashBlockList(BaseListAPIView): - """ - This endpoint allows you to list dashblocks. - - ## Listing dashblocks - - By making a ```GET``` request you can list all the dashblocks for an organization, filtering them as needed. Each - dashblock has the following attributes: - - * **id** - the ID of the story (int) - * **org** - the ID of the org that owns this dashblock (int) - * **dashblock_type** - the type of the dashblock (string) filterable as `dashblock_type`. - * **priority** - the priority of the dashblock (int) - * **title** - the title of the dashblock (string) - * **summary** - the summary of the dashblock (string) - * **content** - the content of the dashblock (string), this can be containing HTML code data as the content is managed as WYSIWYG - * **image_url** - the image url of the dashblock image (string) - * **color** - the color of the dashblock (string) - * **path** - the path of the dashblock to use after the root URL (string) - * **video_id** - the video_id of the dashblock image (string) - * **tags** - the tags of the dashblock (string) - - - Example: - - GET /api/v1/dashblocks/org/1/ - - Response is the list of dashblocks of the organisation - { - "count": 13, - "next": "http://test.ureport.in/api/v1/dashblocks/org/1/?limit=10&offset=10", - "previous": null, - "results": [ - { - "id": 12, - "org": 1, - "dashblock_type": "photos", - "priority": 1, - "title": "CRC@30", - "summary": null, - "content": "Happy Child", - "image_url": "http://test.ureport.in/media/cache/ac/a7/aca7e7ae228e107b9186e77f222faabe.jpg", - "color": null, - "path": null, - "video_id": null, - "tags": null - }, - { - "id": 54, - "org": 1, - "dashblock_type": "photos", - "priority": 0, - "title": "World Mental Day Poll", - "summary": null, - "content": "", - "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", - "color": null, - "link": null, - "video_id": null, - "tags": null - } - ] - } - - """ - - serializer_class = DashblockReadSerializer - model = DashBlock - exclusive_params = ("dashblock_type",) - - def get_queryset(self): - queryset = super().get_queryset() - return queryset.filter(is_active=True).select_related("dashblock_type") - - def filter_queryset(self, queryset): - params = self.request.query_params - - # filter by UUID (optional) - d_type = params.get("dashblock_type") - if d_type: - queryset = queryset.filter(dashblock_type__slug=d_type) - - return queryset - - -class DashBlockDetails(RetrieveAPIView): - """ - This endpoint allows you to a single dashblock. - - ## A single dashblock - - Example: - - GET /api/v1/dashblocks/1/ - - Response is a single dashblock: - - { - "id": 1, - "org": 1, - "dashblock_type": "about", - "priority": 0, - "title": "About", - "summary": "U-report is a free SMS social monitoring.", - "content": "U-report is a free SMS social monitoring tool for community participation, designed to address issues that the population cares about.", - "image_url": "http://test.ureport.in/media/cache/0b/0b/0b0ba4976ac12600c1e1b957d21f5d6d.jpg", - "color": null, - "link": null, - "video_id": null, - "tags": null - }, - """ - - serializer_class = DashblockReadSerializer - model = DashBlock - queryset = DashBlock.objects.filter(is_active=True) From 356d3a5247919c8ede6496411429a39e4b32dd2c Mon Sep 17 00:00:00 2001 From: alviriseup Date: Sun, 9 Jan 2022 19:33:11 +0600 Subject: [PATCH 7/9] Added Tests, Fixed inverted logic --- ureport/api/serializers.py | 39 +++++---- ureport/api/tests.py | 170 +++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 20 deletions(-) diff --git a/ureport/api/serializers.py b/ureport/api/serializers.py index a8f134914..76c313331 100644 --- a/ureport/api/serializers.py +++ b/ureport/api/serializers.py @@ -101,26 +101,25 @@ def get_images(self, obj): ] # Function to use ?fields and ?exclude API calls for specific attributes in stories - # this is for which we can exclude any field def __init__(self, *args, **kwargs): # Don't pass the 'fields' arg up to the superclass request = kwargs.get('context', {}).get('request') - str_fields = request.GET.get('exclude', '') if request else None - str_exclude_fields = request.GET.get('fields', '') if request else None - exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + 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 fields is not None: - # Drop any fields that are not specified in the `fields` argument. - allowed = set(fields) + 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 allowed: + for field_name in exclude_allowed: self.fields.pop(field_name) - elif exclude_fields is not None: - allowed_fields = set(exclude_fields) + 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) @@ -152,23 +151,23 @@ class PollReadSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): # Don't pass the 'fields' arg up to the superclass request = kwargs.get('context', {}).get('request') - str_fields = request.GET.get('exclude', '') if request else None - str_exclude_fields = request.GET.get('fields', '') if request else None - exclude_fields = str_exclude_fields.split(',') if str_exclude_fields else None + 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 fields is not None: - # Drop any fields that are not specified in the `fields` argument. - allowed = set(fields) - print('allowed :',allowed) + 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) existing = set(self.fields) - for field_name in allowed: + for field_name in exclude_allowed: self.fields.pop(field_name) - elif exclude_fields is not None: - allowed_fields = set(exclude_fields) + 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) diff --git a/ureport/api/tests.py b/ureport/api/tests.py index 7cfa9bf73..e6c084650 100644 --- a/ureport/api/tests.py +++ b/ureport/api/tests.py @@ -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] + 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) @@ -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) @@ -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 @@ -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 From fb78a1e4cc66e334ffb723288d07b56e5a33b4e7 Mon Sep 17 00:00:00 2001 From: alviriseup Date: Tue, 11 Jan 2022 19:05:30 +0600 Subject: [PATCH 8/9] Removed whitespaces and unused variables --- ureport/api/serializers.py | 3 --- ureport/api/tests.py | 4 ++-- ureport/api/views.py | 5 ++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ureport/api/serializers.py b/ureport/api/serializers.py index 76c313331..94e9379e8 100644 --- a/ureport/api/serializers.py +++ b/ureport/api/serializers.py @@ -115,7 +115,6 @@ def __init__(self, *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: @@ -162,8 +161,6 @@ def __init__(self, *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) - existing = set(self.fields) for field_name in exclude_allowed: self.fields.pop(field_name) elif fields is not None: diff --git a/ureport/api/tests.py b/ureport/api/tests.py index e6c084650..43f2ff977 100644 --- a/ureport/api/tests.py +++ b/ureport/api/tests.py @@ -402,9 +402,9 @@ def test_polls_by_org_list_with_fields_parameter(self): 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] + polls = [self.second_featured_poll, self.first_featured_poll, self.another_poll, self.reg_poll] for i in range(count_polls): - self.assertEqual(response.data["results"][i]["title"], poll[i].title) + self.assertEqual(response.data["results"][i]["title"], polls[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") diff --git a/ureport/api/views.py b/ureport/api/views.py index 6d158bcbc..62205f777 100644 --- a/ureport/api/views.py +++ b/ureport/api/views.py @@ -572,12 +572,11 @@ 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. @@ -586,7 +585,7 @@ class FeaturedPollList(BaseListAPIView): 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. From 28bc7d04ce73ef3ca4309b4c4eb6ca3e6261f91e Mon Sep 17 00:00:00 2001 From: alviriseup Date: Wed, 12 Jan 2022 12:21:28 +0600 Subject: [PATCH 9/9] Changes commited --- ureport/api/serializers.py | 21 ++++++++++----------- ureport/api/tests.py | 22 ++++++++++++++++++---- ureport/api/views.py | 30 +++++++++++++++--------------- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/ureport/api/serializers.py b/ureport/api/serializers.py index 94e9379e8..5b051bf49 100644 --- a/ureport/api/serializers.py +++ b/ureport/api/serializers.py @@ -103,11 +103,11 @@ def get_images(self, obj): # 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 + 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) @@ -123,7 +123,6 @@ def __init__(self, *args, **kwargs): for field_names in existing_data - allowed_fields: self.fields.pop(field_names) - class Meta: model = Story fields = ( @@ -149,11 +148,11 @@ class PollReadSerializer(serializers.ModelSerializer): # 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 + 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) diff --git a/ureport/api/tests.py b/ureport/api/tests.py index 43f2ff977..8e6530c70 100644 --- a/ureport/api/tests.py +++ b/ureport/api/tests.py @@ -407,7 +407,15 @@ def test_polls_by_org_list_with_fields_parameter(self): self.assertEqual(response.data["results"][i]["title"], polls[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") + 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() @@ -588,9 +596,9 @@ def test_single_poll_with_fields_parameter(self): 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") + 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 @@ -754,7 +762,13 @@ def test_single_story_with_fields_parameter(self): ) 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") + 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 diff --git a/ureport/api/views.py b/ureport/api/views.py index 62205f777..7dae0a838 100644 --- a/ureport/api/views.py +++ b/ureport/api/views.py @@ -262,12 +262,12 @@ 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. @@ -276,7 +276,7 @@ class PollList(BaseListAPIView): 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. @@ -415,21 +415,21 @@ 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. @@ -888,12 +888,12 @@ 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. @@ -902,7 +902,7 @@ class StoryList(BaseListAPIView): 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. @@ -949,21 +949,21 @@ class StoryDetails(RetrieveAPIView): 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