Skip to content

Commit

Permalink
Implement creation of subrabbit feature on backend and frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathaniel81 committed Mar 12, 2024
1 parent d621a9b commit 2f07cbc
Show file tree
Hide file tree
Showing 27 changed files with 572 additions and 196 deletions.
2 changes: 1 addition & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ db.sqlite3
.idea/

# Dependency directories
lib/
# lib/
lib64/
bin/
include/
Expand Down
1 change: 0 additions & 1 deletion backend/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def post(self, request):
if serializer.is_valid():
data = serializer.validated_data
code_data = data.get('code')
print(code_data)
access_token = code_data.get('access_token')
refresh_token = code_data.get('refresh_token')

Expand Down
Binary file modified backend/core/__pycache__/models.cpython-310.pyc
Binary file not shown.
19 changes: 19 additions & 0 deletions backend/core/migrations/0002_alter_subrabbit_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.0.2 on 2024-03-12 12:24

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='subrabbit',
name='name',
field=models.CharField(max_length=255, unique=True, validators=[django.core.validators.MinLengthValidator(3)]),
),
]
19 changes: 19 additions & 0 deletions backend/core/migrations/0003_alter_subrabbit_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.0.2 on 2024-03-12 15:41

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0002_alter_subrabbit_name'),
]

operations = [
migrations.AlterField(
model_name='subrabbit',
name='name',
field=models.CharField(max_length=21, unique=True, validators=[django.core.validators.MinLengthValidator(3), django.core.validators.MaxLengthValidator(21)]),
),
]
4 changes: 3 additions & 1 deletion backend/core/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from django.db import models
from accounts.models import User
from django_editorjs_fields import EditorJsJSONField
from django.core.validators import MinLengthValidator, MaxLengthValidator


class Subrabbit(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, unique=True)
name = models.CharField(max_length=21, unique=True, validators=[
MinLengthValidator(3), MaxLengthValidator(21)])
description = models.CharField(max_length=500, blank=True)
subscribers = models.ManyToManyField(User, related_name='subscriptions', blank=True)
moderators = models.ManyToManyField(User, related_name='moderates', blank=True)
Expand Down
8 changes: 8 additions & 0 deletions backend/core/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from rest_framework import permissions

class IsAuthenticatedOrReadOnly(permissions.BasePermission):
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
return True
else:
return request.user and request.user.is_authenticated
19 changes: 19 additions & 0 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,22 @@ class SubrabbitSerializer(serializers.ModelSerializer):
class Meta:
model = Subrabbit
exclude = ('rules', 'description', )

class SubrabbitSerializer_detailed(serializers.ModelSerializer):
creator = UserSerializer(read_only=True)
subscribers = UserSerializer(many=True, read_only=True)
moderators = UserSerializer(many=True, read_only=True)
members_count = serializers.SerializerMethodField()
is_subscriber = serializers.SerializerMethodField()
# posts = PostSerializer(many=True, read_only=True)

class Meta:
model = Subrabbit
fields = '__all__'

def get_members_count(self, obj):
return obj.subscribers.count()

def get_is_subscriber(self, obj):
user = self.context['request'].user
return obj.subscribers.filter(id=user.id).exists()
66 changes: 62 additions & 4 deletions backend/core/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,69 @@
from rest_framework import generics
from accounts.authenticate import CustomAuthentication
from rest_framework import generics, status
from rest_framework.permissions import SAFE_METHODS
from rest_framework.response import Response
from rest_framework.serializers import ValidationError

from .models import Subrabbit
from .serializers import SubrabbitSerializer
from .permissions import IsAuthenticatedOrReadOnly
from .serializers import SubrabbitSerializer, SubrabbitSerializer_detailed

# from rest_framework.response import Response
# from rest_framework import serializers


class SubrabbitListCreateView(generics.ListCreateAPIView):
serializer_class = SubrabbitSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
authentication_classes = [CustomAuthentication]
queryset = Subrabbit.objects.all().order_by('-created_at')
# permission_classes = [IsAuthenticatedOrReadOnly]

# Apply authentication to unsafe HTTP methods
def get_authenticators(self):
if self.request.method in SAFE_METHODS:
return []
return super().get_authenticators()

# Dynamically select serializer based on HTTP method
def get_serializer_class(self):
if self.request.method == 'GET':
return SubrabbitSerializer_detailed
elif self.request.method == 'POST':
return SubrabbitSerializer

# Override perform_create to add additional fields
def perform_create(self, serializer):
serializer.save(
creator=self.request.user,
subscribers=[self.request.user],
moderators=[self.request.user]
)

# Override create to handle validation errors
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)

try:
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)

except ValidationError as e:
return self.handle_validation_error(e)

except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

headers = self.get_success_headers(serializer.data)
return Response(serializer.data['name'], status=status.HTTP_201_CREATED, headers=headers)

# Method to handle validation errors
def handle_validation_error(self, e):
if 'unique' in e.detail['name'][0].code:
error_message = {
"title": "A subrabbit with this name already exists.",
"detail": "Please choose a different subrabbit name"
}
return Response({"message": [error_message]}, status=status.HTTP_409_CONFLICT)
elif 'min_length' in e.detail['name'][0].code:
return Response(e.detail, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
else:
return Response(e.detail, status=status.HTTP_400_BAD_REQUEST)
Binary file modified backend/db.sqlite3
Binary file not shown.
Loading

0 comments on commit 2f07cbc

Please sign in to comment.