Skip to content
10 changes: 10 additions & 0 deletions project/activities/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from rest_framework import serializers
from .models import Activity


class ActivitySerializer(serializers.ModelSerializer):
"""Serializer for the Activities"""

class Meta:
model = Activity
fields = '__all__'
14 changes: 14 additions & 0 deletions project/activities/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,21 @@
ActivityUpdateView,
)


from activities import views

urlpatterns = [

path(
"api",
views.activity_list,
name="activity_list"
),
path(
"api/<int:id>",
views.activity_details,
name="activity_details"
),
path(
"create",
ActivityCreateView.as_view(),
Expand Down
67 changes: 67 additions & 0 deletions project/activities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,73 @@

from .forms import ActivityModelForm
from .models import Activity
from .serializers import ActivitySerializer

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status


@api_view(['GET', 'POST'])
def activity_list(request):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For cleaner code, let's use class-based API views.

https://www.django-rest-framework.org/tutorial/3-class-based-views/

"""
Circle member(s) can create a Circle Activity via a POST request
Circle members and coordinators can view all Circle Activities via a GET request
"""
circle_id = Activity.objects.values_list("circle_id", flat=True).first()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Activities are logically scoped to a circle, let's pass in the circle_id from the URL:

  • api/v1/circles/{ circle_id }/activities

circle = Circle.objects.get(id=circle_id)

if request.user in circle.companions:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using class-based views, we can use permission_classes for re-usable permission logic:

https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/#object-level-permissions


if request.method == 'GET':
activities = Activity.objects.all()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would seem to be a heavy database query, since it could get a cursor to every activity for every circle. The activities should be scoped to the circle.

serializer = ActivitySerializer(activities, many=True)
return Response(serializer.data)

if request.method == 'POST':
serializer = ActivitySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)

return Response(status=status.HTTP_403_FORBIDDEN)


@api_view(['GET', 'PUT', 'DELETE'])
def activity_details(request, id):
"""
Circle member(s) can update a single Circle Activity via a PUT request
Circle coordinator(s) can delete a single Circle Activity via a DELETE request
Circle members and coordinators can view a single Circle Activity via a GET request
"""
try:
activity = Activity.objects.get(pk=id)
except Activity.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

circle_id = Activity.objects.values_list("circle_id", flat=True).get(pk=id)
circle = Circle.objects.get(id=circle_id)

if request.user in circle.companions:

if request.method == 'GET':
serializer = ActivitySerializer(activity)
return Response(serializer.data)

if request.method == 'PUT':
serializer = ActivitySerializer(activity, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

if request.method == 'DELETE':
if request.user in circle.organizers:
activity.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(status=status.HTTP_403_FORBIDDEN)

return Response(status=status.HTTP_403_FORBIDDEN)


class ActivityCreateView(UserPassesTestMixin, LoginRequiredMixin, View):
Expand Down
1 change: 1 addition & 0 deletions project/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
'rest_framework.authentication.SessionAuthentication',
# 'dj_rest_auth.jwt_auth.JWTCookieAuthentication'
),
"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema",
Expand Down
1 change: 1 addition & 0 deletions project/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
path("i18n/", include("django.conf.urls.i18n")),
path("circles/", include("circles.urls")),
path("__reload__/", include("django_browser_reload.urls")),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
] + media_urlpatterns

handler404 = "error_handling.views.handler404"
Expand Down