Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
37ed1e4
Added Django Rest Framework
Mar 19, 2020
3a33446
Added DRF in requirement.txt
Mar 19, 2020
e82194c
geo-&-people-serializers
vermastuti Apr 9, 2020
2c53b4d
coco-api-version1.0.0
vermastuti May 8, 2020
78ea845
count-param-edited
vermastuti May 9, 2020
04ecd3c
req-txt-updated
vermastuti May 11, 2020
bc688f6
base_settings_updated
vermastuti May 11, 2020
6ed47eb
programs-api-added-and-csrf-auth-bug-exists
vermastuti May 19, 2020
883dc77
resolved-csrf-issue
vermastuti May 19, 2020
798c1b0
standard-urls-and-names
vermastuti May 20, 2020
b1950c9
phone-no-farmers-filter
vermastuti May 20, 2020
bded534
dashboard-F_count
vermastuti May 21, 2020
848893a
match-people-phone-numbers-api
vermastuti May 27, 2020
8e83408
people-post-requests-merged
vermastuti May 28, 2020
db84ff0
limit-queryset-function
vermastuti May 28, 2020
52d242b
coco_api_utils
vermastuti May 28, 2020
fec3889
logging-changes
vermastuti Jun 1, 2020
313009a
logging-with-utils
vermastuti Jun 1, 2020
57d5382
pagination-applied
vermastuti Jun 1, 2020
b61949a
view-permission-IsDGRestricted-added
vermastuti Jun 2, 2020
b6846f3
permissions
vermastuti Jun 4, 2020
f454919
api-app-changes
vermastuti Jun 10, 2020
c6e6687
admin-changes
vermastuti Jun 11, 2020
f0cc1e2
comments-linegaps
vermastuti Jun 11, 2020
2c9f352
code-review-changes
vermastuti Jun 11, 2020
4f4f03b
function-comments
vermastuti Jun 13, 2020
ddf463b
add-line-EOF
vermastuti Jun 13, 2020
85057fa
namespaces-added-to-urls
vermastuti Jun 14, 2020
df3f536
change queries to lower case
Jul 1, 2020
96eddb3
mysql-errors-fixed
Jul 17, 2020
f91bc72
people-FarmersCsvAPIView-limitquery
vermastuti Jul 22, 2020
ea40765
change variable name
sagardg Sep 16, 2020
77c63d0
resolve loading issue & change google charts version
sagardg Sep 16, 2020
a432733
change key name from YEAR, MONTH to year, month
sagardg Sep 16, 2020
cb7fedc
add file
sagardg Sep 16, 2020
e629bf2
Merge remote-tracking branch 'origin/analytics_fix' into coco_api_stuti
vermastuti Sep 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion activities/management/commands/bluefrog_adoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,3 @@ def handle(self, *args, **options):
wtr.writerow(['Not able to Save Adoption in AP Adoption TABLE', member_code, ap_adopt_practice, e])



8 changes: 5 additions & 3 deletions activities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@


class VRPpayment(models.Manager):

"Custom manager filters standard query set with given args."

def __init__(self, partner_id, block_id, start_period, end_period):
super(VRPpayment, self).__init__()
self.start_yyyy = start_period[-4:]
Expand Down Expand Up @@ -95,6 +95,7 @@ class FrontLineWorkerPresent(models.Model):
def __unicode__(self):
return self.worker_type


class Screening(CocoModel):
id = models.AutoField(primary_key=True)
old_coco_id = models.BigIntegerField(editable=False, null=True)
Expand Down Expand Up @@ -147,6 +148,7 @@ class PersonMeetingAttendance(CocoModel):
def __unicode__(self):
return u'%s' % (self.id)


class PersonAdoptPractice(CocoModel):
id = models.AutoField(primary_key=True)
old_coco_id = models.BigIntegerField(editable=False, null=True)
Expand All @@ -173,9 +175,11 @@ def __unicode__(self):

class Meta:
unique_together = ("person", "video", "date_of_adoption")

post_save.connect(save_log, sender=PersonAdoptPractice)
pre_delete.connect(delete_log, sender=PersonAdoptPractice)


class JSLPS_Screening(CocoModel):
id = models.AutoField(primary_key=True)
screenig_code = models.CharField(max_length=100)
Expand Down Expand Up @@ -213,7 +217,6 @@ class Meta:
verbose_name_plural = "JSLPS Adoption"



class AP_Screening(CocoModel):
screening_code = models.CharField(max_length=100)
screening = models.ForeignKey(Screening, null=True, blank=True)
Expand All @@ -240,4 +243,3 @@ class Meta:
verbose_name = "Adoption"
verbose_name_plural = "Adoption"


19 changes: 19 additions & 0 deletions activities/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# rest framework imports
from rest_framework import serializers
# app imports
from activities.models import Screening
from api.utils import DynamicFieldsModelSerializer

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

class ScreeningSerializer(DynamicFieldsModelSerializer):
"""
Serializer class inherited from DynamicFieldsModelSerializer for Screening model
"""

class Meta:
model = Screening
fields = '__all__'
14 changes: 14 additions & 0 deletions activities/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# rest framework imports
from django.conf.urls import url, include, patterns
# app imports
from activities import views

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

urlpatterns=[
url(r'^api/screening', views.ScreeningAPIView.as_view(), name='upavan'),
]

133 changes: 133 additions & 0 deletions activities/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""
This file consists of views for activities.models
"""
# default imports
from django.shortcuts import render
# rest framework imports
from rest_framework import viewsets, generics
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework import status
# app imports
from videos.models import *
from activities.models import *
from activities.serializers import *
# authentication imports
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated
# logging, pagination and permission imports
import time
from api.utils import Utils, CustomPagination
from api.permissions import IsAllowed

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

class ScreeningAPIView( generics.ListCreateAPIView):
'''
This view is specifically written for coco api access.
This class-based view is to query Screening model and provide JSON response.
django-rest-framework based token passed in Header as {'Authorization': 'Token 12345exampleToken'}
is required to access data from this View.
Only POST method is allowed.
GET request sent will show a message : "Method \"GET\" not allowed."
'''

# django-rest-framework TokenAuthentication
authentication_classes = [TokenAuthentication]
permission_classes =[IsAuthenticated and IsAllowed]
pagination_class = CustomPagination
serializer_class = ScreeningSerializer

# GET request
def get(self, request):
return Response({"detail":"Method \"GET\" not allowed"})

# POST request
def post(self, request, *args, **kwargs):
"""
This function can take following optional POST params to filter on Screening obects:
user_created_id - this is id associated with CoCoModel inherited by Screening model,
start_day - takes day part value of a search in date range,
start_month - takes month part value of a search in date range,
start_year - takes year part value of a search in date range,
end_day - takes day part value of a search in date range,
end_month - takes month part value of a search in date range,
end_year - takes year part value of a search in date range,
fields - to pass comma separated value to be returned a value for each Screening object, e.g. pass
fields value as id,user_created to get only these key-value pairs for each Screening object

If none of the above parameters are provided, then all the objects from respective model
will be sent to the response.
"""

start_time = time.time()
utils = Utils()

queryset = Screening.objects.get_queryset().order_by('id')

start_day = request.POST.get('start_day')
start_month = request.POST.get('start_month')
start_year = request.POST.get('start_year')
end_day = request.POST.get('end_day')
end_month = request.POST.get('end_month')
end_year = request.POST.get('end_year')
fields_values = request.POST.get('fields', '') # POST param 'fields', default value is empty string
uc_id = request.POST.get('user_created_id') # POST param 'user_created', default value is empty string

if uc_id:
queryset = queryset.filter(user_created__exact=uc_id) # filters for numeric values with exact match

# case1: all values are present
if start_day and start_month and start_year and end_day and end_month and end_year:
# params type value is string, trimmed spaces,convert to int and then make date by combining values
try:
start_date = datetime.date(int(start_year.strip()), int(start_month.strip()), int(start_day.strip()))
end_date = datetime.date(int(end_year.strip()), int(end_month.strip()), int(end_day.strip()))
queryset = queryset.filter(date__range=(start_date, end_date)) # filters values in date range
except:
utils.logMessage(self, self.post.__name__, "Date error occurred")
# case2: only start values are present
elif start_day and start_month and start_year and not end_day and not end_month and not end_year:
try:
start_date = datetime.date(int(start_year.strip()), int(start_month.strip()), int(start_day.strip()))
queryset = queryset.filter(date__gte=start_date) # filters values greater than or equal to start date
except:
utils.logMessage(self, self.post.__name__, "Start Date error occurred")
# case3: only end values are present
elif not start_day and not start_month and not start_year and end_day and end_month and end_year:
try:
end_date = datetime.date(int(end_year.strip()), int(end_month.strip()), int(end_day.strip()))
queryset = queryset.filter(date__lte=end_date) # filters values less than or equal to end date
except:
utils.logMessage(self, self.post.__name__, "End Date error occurred")

page = self.paginate_queryset(queryset)
if page is not None:
if fields_values: # fields provided in POST request and if not empty serves those fields only
fields_values = [val.strip() for val in fields_values.split(",")]
# updated queryset is passed and fields provided in POST request is passed to the dynamic serializer
serializer = self.get_serializer(page, fields=fields_values, many=True)
else:
# if fields param is empty then all the fields as mentioned in serializer are served to the response
serializer = self.get_serializer(page, many=True)
paginated_response = self.get_paginated_response(serializer.data)
processing_time = time.time() - start_time
utils.logRequest(request, self, self.post.__name__ , processing_time, paginated_response.status_code)
return paginated_response

if fields_values: # fields provided in POST request and if not empty serves those fields only
fields_values = [val.strip() for val in fields_values.split(",")]
# updated queryset is passed and fields provided in POST request is passed to the dynamic serializer
serializer = ScreeningSerializer(queryset, fields=fields_values, many=True)
else:
# if fields param is empty then all the fields as mentioned in serializer are served to the response
serializer = ScreeningSerializer(queryset, many=True)

response = Response(serializer.data)
processing_time = time.time() - start_time
utils.logRequest(request, self, self.post.__name__ , processing_time, response.status_code)
# JSON Response is provided
return response
Empty file added api/__init__.py
Empty file.
Empty file added api/management/__init__.py
Empty file.
Empty file.
82 changes: 82 additions & 0 deletions api/management/commands/insert_views_for_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# django imports
from django.contrib.auth.models import Group
from django.core.management.base import BaseCommand
# csv imports
import unicodecsv as csv
# app imports
from api.models import View
from activities.views import ScreeningAPIView
from geographies.views import VillageAPIView, BlockAPIView, DistrictAPIView, StateAPIView, CountryAPIView, GeoInfoView
from people.views import FarmersJsonAPIView, FarmersCsvAPIView, FarmerInfoView
from programs.views import PartnerAPIView, ProjectAPIView
from videos.views import VideoAPIView

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

# add a view in this list to insert it in database
VIEWS_LIST = {
ScreeningAPIView.__name__,
VillageAPIView.__name__,
BlockAPIView.__name__,
DistrictAPIView.__name__,
StateAPIView.__name__,
CountryAPIView.__name__,
GeoInfoView.__name__,
FarmersJsonAPIView.__name__,
FarmersCsvAPIView.__name__,
FarmerInfoView.__name__,
PartnerAPIView.__name__,
ProjectAPIView.__name__,
VideoAPIView.__name__,
}

class CreateViewAndAddGroups():
"""
Class to create views and add groups for View model
"""

def createAView(self, view_class):
'''
This function adds a view to the database
'''

view = View(view_name = view_class)
view.save()
return

def addAGroupByName(self, view_class_name, group_name):
'''
This function adds a group to a view by view name to the database
'''

view = View.objects.get(view_name=view_class_name)
gr = Group.objects.get(name=group_name)
view.permission_groups.add(gr)
view.save()
return


class Command(BaseCommand):
"""
This class is used to add management commands to insert views in the database
"""

def handle(self, *args, **options):
prod_path = '/home/ubuntu/code/dg_git/api/management/commands/errors.csv'
local_path = '/Users/stuti/Desktop/dg/api/management/commands/errors.csv'
error_file = open(local_path, 'wb')
wrtr = csv.writer(error_file, delimiter=',', quotechar='"')
createAdd = CreateViewAndAddGroups()

for (i, view_name) in enumerate(VIEWS_LIST):
try:
createAdd.createAView(view_name)
# createAdd.addAGroupByName(view_name, "cocoadmin")
except Exception as e:
wrtr.writerow([i, "**insertion-error**", view_name, e])
print(e, "**insertion-error")

error_file.close()
Empty file added api/management/log/logfile
Empty file.
22 changes: 22 additions & 0 deletions api/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('auth', '0006_require_contenttypes_0002'),
]

operations = [
migrations.CreateModel(
name='View',
fields=[
('id', models.AutoField(serialize=False, primary_key=True)),
('view_name', models.CharField(max_length=200)),
('permission_groups', models.ManyToManyField(to='auth.Group')),
],
),
]
Empty file added api/migrations/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions api/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.db import models
from django.contrib.auth.models import Group

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

class View(models.Model):
'''
This is model for View present in the views.py. Groups represent the permitted groups allowed to access it.
'''
id = models.AutoField(primary_key=True)
view_name = models.CharField(max_length=200)
permission_groups = models.ManyToManyField(Group)

def __str__(self):
"Returns the view name and groups names mapped together"
return '%s, %s'%(self.view_name, self.permission_groups)
31 changes: 31 additions & 0 deletions api/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# rest framework imports
from rest_framework import viewsets, generics, status, permissions
from rest_framework.response import Response
# app imports
from api.models import View
# logging imports
import logging

__author__ = "Stuti Verma"
__credits__ = ["Sujit Chaurasia", "Sagar Singh"]
__email__ = "stuti@digitalgreen.org"
__status__ = "Development"

logger = logging
logger = logging.getLogger('coco_api')

class IsAllowed(permissions.BasePermission):
"""
View-level permission to allow group-wise access to the view-based-apis.
"""

def has_permission(self, request, view):
view = View.objects.get(view_name=view.__class__.__name__)
user_groups = request.user.groups.all()
if view.permission_groups.filter(name__in=list(user_groups)).exists():
common_groups = view.permission_groups.filter(name__in=list(user_groups))
logger.info("Permission granted for view: %s to user: %s of group: %s"%(view.view_name, request.user, common_groups))
return True
else:
logger.info("Permission denied for view: %s to user: %s of groups: %s"%(view.view_name, request.user, user_groups))
return False
Loading