diff --git a/docmanager_backend/api/urls.py b/docmanager_backend/api/urls.py index 54b95d0..d0e3e96 100644 --- a/docmanager_backend/api/urls.py +++ b/docmanager_backend/api/urls.py @@ -11,6 +11,7 @@ from drf_spectacular.views import ( urlpatterns = [ path("accounts/", include("accounts.urls")), + path("documents/", include("documents.urls")), path("admin/", admin.site.urls), path("schema/", SpectacularAPIView.as_view(), name="schema"), path( diff --git a/docmanager_backend/config/settings.py b/docmanager_backend/config/settings.py index d201d51..dfcff58 100644 --- a/docmanager_backend/config/settings.py +++ b/docmanager_backend/config/settings.py @@ -66,6 +66,8 @@ INSTALLED_APPS = [ "drf_spectacular", "drf_spectacular_sidecar", "accounts", + "documents", + "django_cleanup.apps.CleanupConfig", ] MIDDLEWARE = [ diff --git a/docmanager_backend/documents/__init__.py b/docmanager_backend/documents/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docmanager_backend/documents/admin.py b/docmanager_backend/documents/admin.py new file mode 100644 index 0000000..4e56f79 --- /dev/null +++ b/docmanager_backend/documents/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from unfold.admin import ModelAdmin + +from .models import Document + + +@admin.register(Document) +class DocumentAdmin(ModelAdmin): + model = Document + search_fields = ["id", "name", "document_type"] + list_display = ["id", "name", "document_type"] diff --git a/docmanager_backend/documents/apps.py b/docmanager_backend/documents/apps.py new file mode 100644 index 0000000..37ce729 --- /dev/null +++ b/docmanager_backend/documents/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DocumentsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "documents" diff --git a/docmanager_backend/documents/migrations/0001_initial.py b/docmanager_backend/documents/migrations/0001_initial.py new file mode 100644 index 0000000..91590c5 --- /dev/null +++ b/docmanager_backend/documents/migrations/0001_initial.py @@ -0,0 +1,50 @@ +# Generated by Django 5.1.3 on 2024-11-23 14:13 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Document", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ( + "document_type", + models.CharField( + choices=[ + ("pdf", "PDF"), + ("image", "Image"), + ("video", "Video"), + ("doc", "Word Document"), + ("excel", "Excel Document"), + ("ppt", "Powerpoint Document"), + ], + max_length=32, + ), + ), + ("file", models.FileField(upload_to="documents/")), + ( + "date_uploaded", + models.DateTimeField( + default=django.utils.timezone.now, editable=False + ), + ), + ], + ), + ] diff --git a/docmanager_backend/documents/migrations/__init__.py b/docmanager_backend/documents/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docmanager_backend/documents/models.py b/docmanager_backend/documents/models.py new file mode 100644 index 0000000..f0fa80a --- /dev/null +++ b/docmanager_backend/documents/models.py @@ -0,0 +1,30 @@ +from django.db import models +from django.utils.timezone import now +import uuid + + +class Document(models.Model): + name = models.CharField(max_length=100) + + DOCUMENT_TYPE_CHOICES = ( + ("pdf", "PDF"), + ("image", "Image"), + ("video", "Video"), + ("doc", "Word Document"), + ("excel", "Excel Document"), + ("ppt", "Powerpoint Document"), + ) + document_type = models.CharField( + max_length=32, choices=DOCUMENT_TYPE_CHOICES, null=False, blank=False + ) + + def upload_to(instance, filename): + _, extension = filename.split(".") + return "documents/%s_%s.%s" % (now, str(uuid.uuid4()), extension) + + file = models.FileField(upload_to=upload_to) + + date_uploaded = models.DateTimeField(default=now, editable=False) + + def __str__(self): + return self.name diff --git a/docmanager_backend/documents/permissions.py b/docmanager_backend/documents/permissions.py new file mode 100644 index 0000000..2e797df --- /dev/null +++ b/docmanager_backend/documents/permissions.py @@ -0,0 +1,10 @@ +from rest_framework.permissions import BasePermission + + +class IsStaff(BasePermission): + """ + Allows access only to users with staff role + """ + + def has_permission(self, request, view): + return bool(request.user and request.user.role == "staff") diff --git a/docmanager_backend/documents/serializers.py b/docmanager_backend/documents/serializers.py new file mode 100644 index 0000000..839e330 --- /dev/null +++ b/docmanager_backend/documents/serializers.py @@ -0,0 +1,33 @@ +from rest_framework import serializers +from .models import Document + + +class DocumentUploadSerializer(serializers.ModelSerializer): + # For staff + file = serializers.FileField() + date_uploaded = serializers.DateTimeField( + format="%m-%d-%Y %I:%M %p", read_only=True + ) + + class Meta: + model = Document + fields = ["id", "name", "file", "document_type", "date_uploaded"] + read_only_fields = ["id", "date-uploaded"] + + +class DocumentDeleteSerializer(serializers.ModelSerializer): + class Meta: + model = Document + fields = ["id"] + + +class DocumentSerializer(serializers.ModelSerializer): + # Read-only serializer + date_uploaded = serializers.DateTimeField( + format="%m-%d-%Y %I:%M %p", read_only=True + ) + + class Meta: + model = Document + fields = ["id", "name", "document_type", "date_uploaded"] + read_only_fields = ["id", "name", "document_type", "date_uploaded"] diff --git a/docmanager_backend/documents/urls.py b/docmanager_backend/documents/urls.py new file mode 100644 index 0000000..47e6240 --- /dev/null +++ b/docmanager_backend/documents/urls.py @@ -0,0 +1,8 @@ +from django.urls import include, path +from .views import DocumentUploadView, DocumentDeleteView, DocumentListView + +urlpatterns = [ + path("upload/", DocumentUploadView.as_view()), + path("delete//", DocumentDeleteView.as_view()), + path("list/", DocumentListView.as_view()), +] diff --git a/docmanager_backend/documents/views.py b/docmanager_backend/documents/views.py new file mode 100644 index 0000000..2964425 --- /dev/null +++ b/docmanager_backend/documents/views.py @@ -0,0 +1,31 @@ +from rest_framework import generics +from .serializers import ( + DocumentSerializer, + DocumentUploadSerializer, + DocumentDeleteSerializer, +) +from .permissions import IsStaff +from .models import Document +from rest_framework.permissions import IsAuthenticated +from rest_framework.pagination import PageNumberPagination + + +class DocumentUploadView(generics.CreateAPIView): + http_method_names = ["post"] + serializer_class = DocumentUploadSerializer + # permission_classes = [IsAuthenticated, IsStaff] + + +class DocumentDeleteView(generics.DestroyAPIView): + http_method_names = ["delete"] + serializer_class = DocumentDeleteSerializer + queryset = Document.objects.all() + # permission_classes = [IsAuthenticated, IsStaff] + + +class DocumentListView(generics.ListAPIView): + http_method_names = ["get"] + serializer_class = DocumentSerializer + queryset = Document.objects.all() + pagination_class = PageNumberPagination + # permission_classes = [IsAuthenticated]