diff --git a/README.md b/README.md new file mode 100644 index 0000000..b358e92 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Library Service API \ No newline at end of file diff --git a/book/__init__.py b/book/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/book/admin.py b/book/admin.py new file mode 100644 index 0000000..3cbb9c6 --- /dev/null +++ b/book/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from .models import Book + + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + list_display = ("title", "author", "cover", "inventory", "daily_fee") + list_filter = ("cover",) + search_fields = ("title", "author") diff --git a/book/apps.py b/book/apps.py new file mode 100644 index 0000000..d317b44 --- /dev/null +++ b/book/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BookConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "book" diff --git a/book/migrations/0001_initial.py b/book/migrations/0001_initial.py new file mode 100644 index 0000000..ec39d63 --- /dev/null +++ b/book/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 5.0.14 on 2026-05-17 09:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Book", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=255)), + ("author", models.CharField(max_length=255)), + ( + "cover", + models.CharField( + choices=[("HARD", "Hardcover"), ("SOFT", "Softcover")], + default="SOFT", + max_length=4, + ), + ), + ("inventory", models.PositiveIntegerField()), + ("daily_fee", models.DecimalField(decimal_places=2, max_digits=6)), + ], + ), + ] diff --git a/book/migrations/__init__.py b/book/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/book/models.py b/book/models.py new file mode 100644 index 0000000..bffe796 --- /dev/null +++ b/book/models.py @@ -0,0 +1,20 @@ +from django.db import models + + +class Book(models.Model): + class CoverChoices(models.TextChoices): + HARD = "HARD", "Hardcover" + SOFT = "SOFT", "Softcover" + + title = models.CharField(max_length=255) + author = models.CharField(max_length=255) + cover = models.CharField( + max_length=4, + choices=CoverChoices.choices, + default=CoverChoices.SOFT + ) + inventory = models.PositiveIntegerField() + daily_fee = models.DecimalField(max_digits=6, decimal_places=2) + + def __str__(self): + return f"{self.title} by {self.author} ({self.cover})" diff --git a/book/serializers.py b/book/serializers.py new file mode 100644 index 0000000..5a6cf3b --- /dev/null +++ b/book/serializers.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from .models import Book + + +class BookSerializer(serializers.ModelSerializer): + class Meta: + model = Book + fields = ("id", "title", "author", "cover", "inventory", "daily_fee") diff --git a/book/tests.py b/book/tests.py new file mode 100644 index 0000000..de8bdc0 --- /dev/null +++ b/book/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/book/urls.py b/book/urls.py new file mode 100644 index 0000000..e060c2d --- /dev/null +++ b/book/urls.py @@ -0,0 +1,12 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from .views import BookViewSet + +router = DefaultRouter() +router.register("", BookViewSet) + +urlpatterns = [ + path("", include(router.urls)), +] + +app_name = "book" diff --git a/book/views.py b/book/views.py new file mode 100644 index 0000000..6fc873b --- /dev/null +++ b/book/views.py @@ -0,0 +1,14 @@ +from rest_framework import viewsets +from rest_framework.permissions import IsAdminUser, AllowAny +from .models import Book +from .serializers import BookSerializer + + +class BookViewSet(viewsets.ModelViewSet): + queryset = Book.objects.all() + serializer_class = BookSerializer + + def get_permissions(self): + if self.action in ["list", "retrieve"]: + return [AllowAny()] + return [IsAdminUser()] diff --git a/library_config/settings.py b/library_config/settings.py index c876e69..98612ee 100644 --- a/library_config/settings.py +++ b/library_config/settings.py @@ -41,6 +41,7 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "book", ] MIDDLEWARE = [ diff --git a/library_config/urls.py b/library_config/urls.py index eae93de..fe75d80 100644 --- a/library_config/urls.py +++ b/library_config/urls.py @@ -1,23 +1,7 @@ -""" -URL configuration for library_config project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" - from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), + path("api/books/", include("book.urls", namespace="book")), ]