Commit e85459b8 authored by Ristylou Dolar's avatar Ristylou Dolar

Update model fields, pagination, serializer validations and viewset CRUDs

parent 68bbe2f0
...@@ -30,3 +30,6 @@ local_*.py ...@@ -30,3 +30,6 @@ local_*.py
.venv .venv
venv/ venv/
ENV/ ENV/
#vscode
.vscode/
# Generated by Django 2.1.5 on 2019-01-11 16:21 # Generated by Django 2.1.5 on 2019-05-14 15:45
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
...@@ -22,6 +22,9 @@ class Migration(migrations.Migration): ...@@ -22,6 +22,9 @@ class Migration(migrations.Migration):
('endpoint_url', models.CharField(max_length=200)), ('endpoint_url', models.CharField(max_length=200)),
('is_need_auth', models.BooleanField(default=False)), ('is_need_auth', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=True)), ('is_active', models.BooleanField(default=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
], ],
options={ options={
'db_table': 'api_endpoints', 'db_table': 'api_endpoints',
...@@ -34,11 +37,33 @@ class Migration(migrations.Migration): ...@@ -34,11 +37,33 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=200, unique=True)), ('name', models.CharField(max_length=200, unique=True)),
('base_url', models.CharField(max_length=200)), ('base_url', models.CharField(max_length=200)),
('service_url', models.CharField(max_length=200)), ('service_url', models.CharField(max_length=200)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
], ],
options={ options={
'db_table': 'api_services', 'db_table': 'api_services',
}, },
), ),
migrations.CreateModel(
name='Application',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, unique=True)),
('theme', models.IntegerField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
],
options={
'db_table': 'application',
},
),
migrations.AddField(
model_name='apiservice',
name='application',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='api.Application'),
),
migrations.AddField( migrations.AddField(
model_name='apiendpoint', model_name='apiendpoint',
name='service', name='service',
......
# Generated by Django 2.1.5 on 2019-05-11 13:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Application',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, unique=True)),
('theme', models.IntegerField()),
],
options={
'db_table': 'application',
},
),
migrations.AddField(
model_name='apiservice',
name='application',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.DO_NOTHING, to='api.Application'),
preserve_default=False,
),
]
from django.db import models from django.db import models
from django.utils import timezone
class Application(models.Model): class Application(models.Model):
application_no = models.CharField(max_length=250)
name = models.CharField(max_length=200, unique=True) name = models.CharField(max_length=200, unique=True)
theme = models.IntegerField() theme = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
deleted_at = models.DateTimeField(null=True, blank=True)
def delete(self):
self.deleted_at = timezone.now()
self.save()
def __str__(self): def __str__(self):
return self.name return self.name
...@@ -13,10 +22,18 @@ class Application(models.Model): ...@@ -13,10 +22,18 @@ class Application(models.Model):
class APIService(models.Model): class APIService(models.Model):
api_service_no = models.CharField(max_length=250)
name = models.CharField(max_length=200, unique=True) name = models.CharField(max_length=200, unique=True)
base_url = models.CharField(max_length=200) base_url = models.CharField(max_length=200)
service_url = models.CharField(max_length=200) service_url = models.CharField(max_length=200)
application = models.ForeignKey(Application, on_delete=models.DO_NOTHING) application = models.ForeignKey(Application, on_delete=models.DO_NOTHING)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
deleted_at = models.DateTimeField(null=True, blank=True)
def delete(self):
self.deleted_at = timezone.now()
self.save()
def __str__(self): def __str__(self):
return self.name return self.name
...@@ -26,6 +43,7 @@ class APIService(models.Model): ...@@ -26,6 +43,7 @@ class APIService(models.Model):
class APIEndpoint(models.Model): class APIEndpoint(models.Model):
api_endpoint_no = models.CharField(max_length=250)
service = models.ForeignKey(APIService, on_delete=models.DO_NOTHING) service = models.ForeignKey(APIService, on_delete=models.DO_NOTHING)
name = models.CharField(max_length=200, unique=True) name = models.CharField(max_length=200, unique=True)
description = models.CharField(max_length=255, null=True, blank=True) description = models.CharField(max_length=255, null=True, blank=True)
...@@ -33,7 +51,14 @@ class APIEndpoint(models.Model): ...@@ -33,7 +51,14 @@ class APIEndpoint(models.Model):
endpoint_url = models.CharField(max_length=200) endpoint_url = models.CharField(max_length=200)
is_need_auth = models.BooleanField(default=False) is_need_auth = models.BooleanField(default=False)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
deleted_at = models.DateTimeField(null=True, blank=True)
def delete(self):
self.deleted_at = timezone.now()
self.save()
def __str__(self): def __str__(self):
return self.name return self.name
......
from rest_framework import serializers from rest_framework import serializers
from .models import APIService, APIEndpoint, Application from .models import APIService, APIEndpoint, Application
from api.utils import BadRequestException
from rest_framework.exceptions import ValidationError
class ApplicationSerializer(serializers.ModelSerializer): class ApplicationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Application model = Application
fields = ("id", "name", "theme") fields = ('id', 'application_no', 'name', 'theme', 'created_at', 'updated_at', 'deleted_at')
read_only_fields = ('id', 'application_no', 'created_at', 'updated_at', 'deleted_at')
def is_valid(self, raise_exception=False):
assert not hasattr(self, 'restore_object'), (
'Serializer `%s.%s` has old-style version 2 `.restore_object()` '
'that is no longer compatible with REST framework 3. '
'Use the new-style `.create()` and `.update()` methods instead.' %
(self.__class__.__module__, self.__class__.__name__)
)
assert hasattr(self, 'initial_data'), (
'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
if not hasattr(self, '_validated_data'):
try:
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
#if validation failed
if self._errors and raise_exception:
error_message = {}
message = str(self.errors)
for k, v in self.errors.items():
message = str(v)
start = message.find('string=') + 8
end = message.find(', code=') - 1
message = message[start:end]
error_message[str(k)] = message
raise BadRequestException(error_message)
return not bool(self._errors)
class APIServiceSerializer(serializers.ModelSerializer): class APIServiceSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = APIService model = APIService
fields = ('id', 'name', 'base_url', 'service_url', 'application') fields = ('id', 'api_service_no', 'name', 'base_url', 'service_url', 'application', 'created_at', 'updated_at', 'deleted_at')
read_only_fields = ('id', 'api_service_no', 'created_at', 'updated_at', 'deleted_at')
class APIEndpointSerializer(serializers.ModelSerializer): class APIEndpointSerializer(serializers.ModelSerializer):
...@@ -20,6 +65,7 @@ class APIEndpointSerializer(serializers.ModelSerializer): ...@@ -20,6 +65,7 @@ class APIEndpointSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = APIEndpoint model = APIEndpoint
fields = ( fields = (
'id', 'service', 'service_name', 'name', 'description', 'id', 'api_endpoint_no', 'service', 'service_name', 'name', 'description',
'http_method', 'endpoint_url', 'is_need_auth', 'is_active' 'http_method', 'endpoint_url', 'is_need_auth', 'is_active', 'created_at', 'updated_at', 'deleted_at'
) )
read_only_fields = ('id', 'api_endpoint_no', 'created_at', 'updated_at', 'deleted_at')
...@@ -6,10 +6,14 @@ from rest_framework import status ...@@ -6,10 +6,14 @@ from rest_framework import status
from django_filters import FilterSet from django_filters import FilterSet
from django_filters import rest_framework as filters from django_filters import rest_framework as filters
from .models import APIEndpoint from .models import APIEndpoint
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
VALIDATE_TOKEN_URL = settings.VALIDATE_TOKEN_URL VALIDATE_TOKEN_URL = settings.VALIDATE_TOKEN_URL
class BadRequestException(Exception):
pass
class APIEndpointFilter(FilterSet): class APIEndpointFilter(FilterSet):
service = filters.CharFilter('service__name') service = filters.CharFilter('service__name')
...@@ -116,3 +120,23 @@ class Helper: ...@@ -116,3 +120,23 @@ class Helper:
return self._response_data({'message': str(e)}, return self._response_data({'message': str(e)},
status.HTTP_500_INTERNAL_SERVER_ERROR, status.HTTP_500_INTERNAL_SERVER_ERROR,
self._headers) self._headers)
class CustomPagination(PageNumberPagination):
page_size = 5 # Set number of result to display per page
max_page_size = 50 # Sets max page size that user may request
page_query_param = 'page'
page_size_query_param = 'page_size'
def get_paginated_response(self, data):
return Response({
'page_number': self.page.number,
'size_per_page': self.page.paginator.per_page,
'total_pages': self.page.paginator.num_pages,
'total': self.page.paginator.count,
'code': data['code'],
'status': data['status'],
'message': data['message'],
'results': data['results']
})
...@@ -7,16 +7,197 @@ from .models import APIService, APIEndpoint, Application ...@@ -7,16 +7,197 @@ from .models import APIService, APIEndpoint, Application
from .serializers import ( from .serializers import (
APIServiceSerializer, APIEndpointSerializer, ApplicationSerializer APIServiceSerializer, APIEndpointSerializer, ApplicationSerializer
) )
from .utils import APIEndpointFilter, Helper from .utils import (APIEndpointFilter, Helper, CustomPagination, BadRequestException)
class ApplicationViewSet(viewsets.ModelViewSet): class ApplicationViewSet(viewsets.ModelViewSet):
http_method_names = [ http_method_names = [
'get', 'post', 'put', 'patch', 'head', 'options', 'trace' 'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'
] ]
lookup_field = 'id' lookup_field = 'pk'
queryset = Application.objects.all() queryset = Application.objects.all()
serializer_class = ApplicationSerializer serializer_class = ApplicationSerializer
pagination_class = CustomPagination
# CREATE Application
def create(self, request, *args, **kwargs):
try:
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
message = {
'code': 201,
'status': 'success',
'message': 'New application created',
'results': serializer.data
}
return Response(message)
except BadRequestException as e:
message = {
'code': 400,
'status': 'failed',
'message': '' + str(e),
}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# SHOW LIST of Applications
def list(self, request, *args, **kwargs):
try:
queryset = Application.objects.filter(deleted_at__exact=None)
if not queryset.exists():
message = {
'code': 404,
'status': 'failed',
'message': 'No records found'
}
return Response(message, status=status.HTTP_404_NOT_FOUND)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = {
'code': 200,
'status': 'success',
'message': 'List of applications found',
'results': serializer.data
}
return self.get_paginated_response(message)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# Show specific item
def retrieve(self, request, *args, **kwargs):
try:
id = self.kwargs['pk']
queryset = Application.objects.filter(id=id)
serializer = self.get_serializer(queryset, many=True)
if not queryset.exists():
message = {
'code': 404,
'status': 'failed',
'message': 'No records found'
}
return Response(message, status=status.HTTP_404_NOT_FOUND)
else:
message = {
'code': 200,
'status': 'success',
'message': 'Application retrieved',
'results': serializer.data
}
return Response(message, status=status.HTTP_200_OK)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# Update Application
def update(self, request, *args, **kwargs):
try:
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
instance = self.get_object()
if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {}
message = {
'code': 200,
'status': 'success',
'message': 'Application updated',
'results': serializer.data
}
return Response(message)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# SOFT DELETE
def destroy(self, request, *args, **kwargs):
try:
instance = self.get_object()
self.perform_destroy(instance)
message = {
'code': 200,
'status': 'Success',
'message': 'Application deleted'
}
return Response(message, status=status.HTTP_200_OK)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# PATCH - RESTORE archived application
# /archived - show list of archived marital status
@action(methods=["GET"], detail=False)
def archived(self, request, pk=None):
try:
queryset = Application.objects.filter(deleted_at__isnull=False)
if not queryset.exists():
message = {
'code': 404,
'status': 'failed',
'message': 'No records found'
}
return Response(message, status=status.HTTP_404_NOT_FOUND)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = {
'code': 200,
'status': 'success',
'message': 'Archived applications found',
'results': serializer.data
}
return self.get_paginated_response(message)
except Exception as e:
message = {
'code': 500,
'status': 'failed',
'message': 'Request was not able to process' + str(e),
}
return Response(message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@action(methods=['GET'], detail=True) @action(methods=['GET'], detail=True)
def services(self, request, id=None): def services(self, request, id=None):
......
...@@ -20,5 +20,5 @@ swagger = get_swagger_view(title='API Main End Point') ...@@ -20,5 +20,5 @@ swagger = get_swagger_view(title='API Main End Point')
urlpatterns = [ urlpatterns = [
path('docs/', swagger), path('docs/', swagger),
path('api/v1/', include('api.urls')), path('', include('api.urls')),
] ]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment