├── CORE ├── __init__.py ├── __pycache__ │ ├── urls.cpython-311.pyc │ ├── wsgi.cpython-311.pyc │ ├── __init__.cpython-311.pyc │ └── settings.cpython-311.pyc ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── books ├── __init__.py ├── migrations │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-311.pyc │ │ └── 0001_initial.cpython-311.pyc │ └── 0001_initial.py ├── tests.py ├── admin.py ├── __pycache__ │ ├── admin.cpython-311.pyc │ ├── apps.cpython-311.pyc │ ├── urls.cpython-311.pyc │ ├── views.cpython-311.pyc │ ├── models.cpython-311.pyc │ ├── __init__.cpython-311.pyc │ └── serializers.cpython-311.pyc ├── apps.py ├── serializers.py ├── urls.py ├── models.py └── views.py ├── accounts ├── __init__.py ├── migrations │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-311.pyc │ │ └── 0001_initial.cpython-311.pyc │ └── 0001_initial.py ├── admin.py ├── tests.py ├── __pycache__ │ ├── apps.cpython-311.pyc │ ├── urls.cpython-311.pyc │ ├── admin.cpython-311.pyc │ ├── models.cpython-311.pyc │ ├── tokens.cpython-311.pyc │ ├── views.cpython-311.pyc │ ├── __init__.cpython-311.pyc │ └── serializers.cpython-311.pyc ├── apps.py ├── models.py ├── urls.py ├── serializers.py └── views.py ├── .gitignore ├── requirements.txt ├── manage.py └── readme.md /CORE/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /books/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /books/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /env 2 | /CORE/.env -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /books/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /books/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/requirements.txt -------------------------------------------------------------------------------- /CORE/__pycache__/urls.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/CORE/__pycache__/urls.cpython-311.pyc -------------------------------------------------------------------------------- /CORE/__pycache__/wsgi.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/CORE/__pycache__/wsgi.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/admin.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/admin.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/apps.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/apps.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/urls.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/urls.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/views.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/views.cpython-311.pyc -------------------------------------------------------------------------------- /CORE/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/CORE/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /CORE/__pycache__/settings.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/CORE/__pycache__/settings.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/apps.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/apps.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/urls.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/urls.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/models.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/models.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/admin.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/admin.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/models.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/models.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/tokens.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/tokens.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/views.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/views.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /books/__pycache__/serializers.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/__pycache__/serializers.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/serializers.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/__pycache__/serializers.cpython-311.pyc -------------------------------------------------------------------------------- /books/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BooksConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'books' 7 | -------------------------------------------------------------------------------- /books/migrations/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/migrations/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'accounts' 7 | -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/migrations/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /books/migrations/__pycache__/0001_initial.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/books/migrations/__pycache__/0001_initial.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/0001_initial.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Supraav/DRF-Library-Management-System/master/accounts/migrations/__pycache__/0001_initial.cpython-311.pyc -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class User(models.Model): 5 | UserID = models.AutoField(primary_key=True) 6 | Name = models.CharField(max_length=100) 7 | Email = models.EmailField(unique=True) 8 | Password = models.CharField(max_length=128) 9 | MembershipDate = models.DateField(auto_now_add=True) 10 | 11 | class Meta: 12 | db_table='UserAccounts' -------------------------------------------------------------------------------- /CORE/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for CORE project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CORE.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /CORE/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for CORE project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CORE.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path,include 3 | from accounts.views import UserRegistrationAPIView,UserDeleteView,GetAllUsersAPIView,OneUserDetailsAPIView 4 | 5 | urlpatterns = [ 6 | path('register',UserRegistrationAPIView.as_view(),name='register'), 7 | path('delete/',UserDeleteView.as_view(),name='delete'), 8 | 9 | path('getall',GetAllUsersAPIView.as_view(),name='getall'), 10 | path('getone/', OneUserDetailsAPIView.as_view(), name='user-details'), 11 | 12 | # path('login',TokenAPIView.as_view(),name='login') 13 | ] -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CORE.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.1 on 2024-02-01 11:25 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='User', 16 | fields=[ 17 | ('UserID', models.AutoField(primary_key=True, serialize=False)), 18 | ('Name', models.CharField(max_length=100)), 19 | ('Email', models.EmailField(max_length=254, unique=True)), 20 | ('Password', models.CharField(max_length=128)), 21 | ('MembershipDate', models.DateField(auto_now_add=True)), 22 | ], 23 | options={ 24 | 'db_table': 'UserAccounts', 25 | }, 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /books/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from accounts.models import User 3 | from books.models import Book,BookDetails,BorrowedBooks 4 | 5 | class BookSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model=Book 8 | fields='__all__' 9 | 10 | class BookDetailSerializer(serializers.ModelSerializer): 11 | class Meta: 12 | model=BookDetails 13 | fields=['DetailsID','NumberOfPages','Publisher','Language','Book_id'] 14 | 15 | class BorrowBookSerializer(serializers.ModelSerializer): 16 | class Meta: 17 | model=BorrowedBooks 18 | fields=['id','BorrowDate','user','book'] 19 | read_only_fields = ['id'] 20 | 21 | class BorrowBookReturnSerializer(serializers.ModelSerializer): 22 | class Meta: 23 | model=BorrowedBooks 24 | fields=['id','ReturnDate','user'] 25 | read_only_fields = ['id'] -------------------------------------------------------------------------------- /books/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path,include 2 | from books.views import (AddBookView, 3 | GetAllBooksView, 4 | GetOneBookView, 5 | AssignUpdateBookView, 6 | BorrowBookView, 7 | ReturnBookView, 8 | ListAllBorrowedBooksView) 9 | 10 | urlpatterns = [ 11 | path('addbook',AddBookView.as_view(),name='add_book'), 12 | path('listallbooks',GetAllBooksView.as_view(),name='getallbooks'), 13 | path('getonebookdetails/',GetOneBookView.as_view(),name='getonebook'), 14 | path('modifybook/',AssignUpdateBookView.as_view(),name='modifybook'), 15 | path('borrowbook',BorrowBookView.as_view(),name='borrowbook'), 16 | path('returnbook/',ReturnBookView.as_view(),name='returnbook'), 17 | path('listborrowedbook',ListAllBorrowedBooksView.as_view(),name='list-borrowed-books'), 18 | ] -------------------------------------------------------------------------------- /accounts/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from accounts.models import User 3 | from django.contrib.auth.hashers import make_password 4 | 5 | 6 | class UsersSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = User 9 | fields = '__all__' 10 | 11 | #Register 12 | class UserRegisterSerializer(serializers.ModelSerializer): 13 | class Meta: 14 | model = User 15 | fields = ['Name', 'Email', 'Password'] 16 | extra_kwargs = {'Password': {'write_only': True}} 17 | 18 | def validate(self, data): 19 | email_exists=User.objects.filter(Email=data['Email']).exists() 20 | if email_exists: 21 | raise serializers.ValidationError("Unique emails required. ") 22 | return data 23 | 24 | def create(self, validated_data): 25 | validated_data['Password'] = make_password(validated_data['Password']) 26 | user = User.objects.create(**validated_data) 27 | return user 28 | 29 | class UserLoginSerializer(serializers.Serializer): 30 | Email = serializers.EmailField() 31 | Password = serializers.CharField(write_only=True) 32 | 33 | -------------------------------------------------------------------------------- /books/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from accounts.models import User 3 | 4 | # Create your models here. 5 | 6 | class Book(models.Model): 7 | BookID = models.AutoField(primary_key=True) 8 | Title = models.CharField(max_length=255) 9 | ISBN = models.CharField(max_length=13, unique=True) 10 | PublishedDate = models.DateField() 11 | Genre = models.CharField(max_length=50) 12 | 13 | class Meta: 14 | db_table='Book' 15 | 16 | class BookDetails(models.Model): 17 | DetailsID = models.AutoField(primary_key=True) 18 | Book = models.OneToOneField(Book, on_delete=models.CASCADE) 19 | NumberOfPages = models.IntegerField() 20 | Publisher = models.CharField(max_length=100) 21 | Language = models.CharField(max_length=50) 22 | 23 | class Meta: 24 | db_table='BookDetails' 25 | 26 | class BorrowedBooks(models.Model): 27 | user = models.ForeignKey(User, on_delete=models.CASCADE) 28 | book = models.ForeignKey(Book, on_delete=models.CASCADE) 29 | BorrowDate = models.DateField() 30 | ReturnDate = models.DateField(null=True, blank=True) 31 | 32 | class Meta: 33 | db_table='BorrowedBooks' 34 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Library Management System 2 | 3 | A LMS created using Django Rest Framework to create users, add book and its details , borrow and return books. 4 | 5 | The project runs on [localhost:8080](http://localhost:8080) by default. 6 | 7 | ### Start: 8 | 9 | git clone [url] 10 | 11 | ### Setup Environment 12 | 13 | pip -m venv env 14 | 15 | ### Activate Envorinment 16 | env\Scripts\activate 17 | 18 | ### Install Requirements 19 | 20 | pip install -r requirements.txt 21 | 22 | ### setup postgreSQL 23 | 24 | Create a Database in PostgreSQL. 25 | In CORE, create a .env file and load your database configurations as : 26 | 27 | DATABASE_ENGINE=django.db.backends.postgresql_psycopg2 28 | DATABASE_NAME='your_db_name' 29 | DATABASE_USER='your_pg_user' 30 | DATABASE_PASSWORD='your_pg_pw' 31 | DATABASE_HOST='your_pg_host' 32 | DATABASE_PORT='your_pg_port' 33 | 34 | ### Make migrations 35 | python manage.py makemigrations 36 | python manage.py migrate 37 | 38 | ### Run the Server 39 | 40 | python manage.py runserver 41 | 42 | ### the documentation is hosted on SwaggerUI 43 | [http://127.0.0.1:8000/swagger/](http://127.0.0.1:8000/swagger/) 44 | 45 | -------------------------------------------------------------------------------- /CORE/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for CORE project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/5.0/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import URLPattern, path,include 19 | 20 | #swagger 21 | from drf_yasg.views import get_schema_view 22 | from drf_yasg import openapi 23 | from rest_framework_swagger.views import get_swagger_view 24 | from rest_framework import permissions 25 | from django.conf import settings 26 | 27 | schema_view = get_schema_view( 28 | openapi.Info( 29 | title="library Management System", 30 | default_version='v1', 31 | description="library API ", 32 | ), 33 | public=True, 34 | permission_classes=(permissions.AllowAny,), 35 | ) 36 | 37 | # urlpatterns = [ 38 | # path('admin/', admin.site.urls), 39 | # path('api/v1/', 40 | # include([ 41 | # path('accounts/',include('accounts.urls')), 42 | # path('books/',include('books.urls')), 43 | # path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger'), 44 | 45 | # ]) 46 | # ), 47 | # path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) 48 | 49 | # ] 50 | 51 | urlpatterns = [ 52 | path('admin/', admin.site.urls), 53 | 54 | path('accounts/',include('accounts.urls')), 55 | path('books/',include('books.urls')), 56 | 57 | path('swagger/', schema_view.with_ui('swagger', cache_timeout=0),name='schema-swagger-ui'), 58 | 59 | path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) 60 | 61 | ] 62 | -------------------------------------------------------------------------------- /books/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.1 on 2024-02-01 11:25 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ('accounts', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='Book', 18 | fields=[ 19 | ('BookID', models.AutoField(primary_key=True, serialize=False)), 20 | ('Title', models.CharField(max_length=255)), 21 | ('ISBN', models.CharField(max_length=13, unique=True)), 22 | ('PublishedDate', models.DateField()), 23 | ('Genre', models.CharField(max_length=50)), 24 | ], 25 | options={ 26 | 'db_table': 'Book', 27 | }, 28 | ), 29 | migrations.CreateModel( 30 | name='BookDetails', 31 | fields=[ 32 | ('DetailsID', models.AutoField(primary_key=True, serialize=False)), 33 | ('NumberOfPages', models.IntegerField()), 34 | ('Publisher', models.CharField(max_length=100)), 35 | ('Language', models.CharField(max_length=50)), 36 | ('Book', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='books.book')), 37 | ], 38 | options={ 39 | 'db_table': 'BookDetails', 40 | }, 41 | ), 42 | migrations.CreateModel( 43 | name='BorrowedBooks', 44 | fields=[ 45 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 46 | ('BorrowDate', models.DateField()), 47 | ('ReturnDate', models.DateField(blank=True, null=True)), 48 | ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.book')), 49 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.user')), 50 | ], 51 | options={ 52 | 'db_table': 'BorrowedBooks', 53 | }, 54 | ), 55 | ] 56 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | 2 | from rest_framework.generics import GenericAPIView 3 | from rest_framework.response import Response 4 | from rest_framework import status 5 | from rest_framework.permissions import AllowAny,IsAuthenticated 6 | from .serializers import UserRegisterSerializer,UsersSerializer 7 | from accounts.models import User 8 | from rest_framework_simplejwt.tokens import RefreshToken 9 | from django.contrib.auth.hashers import check_password 10 | 11 | # Create your views here. 12 | 13 | #register User 14 | class UserRegistrationAPIView(GenericAPIView): 15 | permission_classes = (AllowAny,) 16 | serializer_class = UserRegisterSerializer 17 | def post(self, request): 18 | try: 19 | serializer = UserRegisterSerializer(data=request.data) 20 | if serializer.is_valid(): 21 | serializer.save() 22 | return Response( 23 | serializer.data, 24 | status=status.HTTP_201_CREATED) 25 | 26 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 27 | except Exception as e: 28 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 29 | 30 | # DELETE the USER 31 | class UserDeleteView(GenericAPIView): 32 | def delete(self,request,user_id): 33 | try: 34 | user=User.objects.get(UserID=user_id) 35 | if user: 36 | user.delete() 37 | return Response({'msg': 'User deleted successfully'}, status=status.HTTP_200_OK) 38 | except User.DoesNotExist: 39 | return Response({'msg': 'User doesnot exist'}, status=status.HTTP_404_NOT_FOUND) 40 | except Exception as e: 41 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 42 | 43 | #get all users 44 | class GetAllUsersAPIView(GenericAPIView): 45 | serializer_class = UsersSerializer 46 | def get(self, request): 47 | try: 48 | users=User.objects.all() 49 | serializer = UsersSerializer(users,many=True) 50 | return Response({"Info": serializer.data}, status=status.HTTP_200_OK) 51 | except Exception as e: 52 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 53 | 54 | # get one user 55 | class OneUserDetailsAPIView(GenericAPIView): 56 | serializer_class = UsersSerializer 57 | def get(self, request, user_id): 58 | try: 59 | user = User.objects.get(UserID=user_id) 60 | serializer = UsersSerializer(user) 61 | return Response(serializer.data, status=status.HTTP_200_OK) 62 | except User.DoesNotExist: 63 | return Response({'msg': 'User not found'}, status=status.HTTP_404_NOT_FOUND) 64 | 65 | # #Login User 66 | # class TokenAPIView(GenericAPIView): 67 | # permission_classes = (AllowAny,) 68 | # serializer_class = UserLoginSerializer 69 | # def post(self, request): 70 | # email = request.data.get('Email') 71 | # password = request.data.get('Password') 72 | 73 | # try: 74 | # user = User.objects.get(Email=email) 75 | # except User.DoesNotExist: 76 | # return Response({'error': 'Invalid email or password'}, status=status.HTTP_401_UNAUTHORIZED) 77 | 78 | # if check_password(password, user.Password): 79 | 80 | # # Generate JWT tokens 81 | # refresh = RefreshToken.for_user(user) 82 | # access_token = str(refresh.access_token) 83 | 84 | # return Response({'access_token': access_token,'refresh_token':str(refresh)}, status=status.HTTP_200_OK) 85 | # else: 86 | # return Response({'error': 'Invalid email or password'}, status=status.HTTP_401_UNAUTHORIZED) 87 | -------------------------------------------------------------------------------- /CORE/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for CORE project. 3 | 4 | Generated by 'django-admin startproject' using Django 5.0.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/5.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | from datetime import timedelta 16 | import environ 17 | 18 | #environment variables 19 | env = environ.Env() 20 | environ.Env.read_env() 21 | 22 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 23 | BASE_DIR = Path(__file__).resolve().parent.parent 24 | 25 | 26 | # Quick-start development settings - unsuitable for production 27 | # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ 28 | 29 | # SECURITY WARNING: keep the secret key used in production secret! 30 | SECRET_KEY = 'django-insecure-24t3$kb&a#%od%tg2r!y6+ddi3irxfzd7)u=fq8hwh86@qt=*_' 31 | 32 | # SECURITY WARNING: don't run with debug turned on in production! 33 | DEBUG = True 34 | 35 | ALLOWED_HOSTS = [] 36 | 37 | 38 | # Application definition 39 | 40 | INSTALLED_APPS = [ 41 | 'django.contrib.admin', 42 | 'django.contrib.auth', 43 | 'django.contrib.contenttypes', 44 | 'django.contrib.sessions', 45 | 'django.contrib.messages', 46 | 'django.contrib.staticfiles', 47 | 48 | 'rest_framework', 49 | 'rest_framework.authtoken', 50 | 'rest_framework_simplejwt', 51 | 'drf_yasg', 52 | 'rest_framework_swagger', 53 | 54 | 'accounts', 55 | 'books', 56 | ] 57 | 58 | MIDDLEWARE = [ 59 | 'django.middleware.security.SecurityMiddleware', 60 | 'django.contrib.sessions.middleware.SessionMiddleware', 61 | 'django.middleware.common.CommonMiddleware', 62 | 'django.middleware.csrf.CsrfViewMiddleware', 63 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 64 | 'django.contrib.messages.middleware.MessageMiddleware', 65 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 66 | ] 67 | 68 | ROOT_URLCONF = 'CORE.urls' 69 | 70 | TEMPLATES = [ 71 | { 72 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 73 | 'DIRS': [], 74 | 'APP_DIRS': True, 75 | 'OPTIONS': { 76 | 'context_processors': [ 77 | 'django.template.context_processors.debug', 78 | 'django.template.context_processors.request', 79 | 'django.contrib.auth.context_processors.auth', 80 | 'django.contrib.messages.context_processors.messages', 81 | ], 82 | }, 83 | }, 84 | ] 85 | 86 | WSGI_APPLICATION = 'CORE.wsgi.application' 87 | 88 | 89 | # Database 90 | # https://docs.djangoproject.com/en/5.0/ref/settings/#databases 91 | 92 | DATABASES = { 93 | # 'default': { 94 | # 'ENGINE': 'django.db.backends.sqlite3', 95 | # 'NAME': BASE_DIR / 'db.sqlite3', 96 | # } 97 | 98 | 'default': { 99 | 'ENGINE': env('DATABASE_ENGINE'), 100 | 'NAME': env('DATABASE_NAME'), 101 | 'USER': env('DATABASE_USER'), 102 | 'PASSWORD': env('DATABASE_PASSWORD'), 103 | 'HOST': env('DATABASE_HOST'), 104 | 'PORT': env('DATABASE_PORT'), 105 | } 106 | } 107 | 108 | 109 | # Password validation 110 | # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators 111 | 112 | AUTH_PASSWORD_VALIDATORS = [ 113 | { 114 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 115 | }, 116 | { 117 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 118 | }, 119 | { 120 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 121 | }, 122 | { 123 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 124 | }, 125 | ] 126 | 127 | 128 | 129 | # Internationalization 130 | # https://docs.djangoproject.com/en/5.0/topics/i18n/ 131 | 132 | LANGUAGE_CODE = 'en-us' 133 | 134 | TIME_ZONE = 'UTC' 135 | 136 | USE_I18N = True 137 | 138 | USE_TZ = True 139 | 140 | 141 | # Static files (CSS, JavaScript, Images) 142 | # https://docs.djangoproject.com/en/5.0/howto/static-files/ 143 | 144 | STATIC_URL = 'static/' 145 | 146 | # Default primary key field type 147 | # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field 148 | 149 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 150 | 151 | #REST FRAMEWORK 152 | REST_FRAMEWORK={ 153 | 'DEFAULT_PERMISSION_CLASSES': [ 154 | 'rest_framework.permissions.AllowAny', 155 | ] 156 | , 157 | 'DEFAULT_AUTHENTICATION_CLASSES': [ 158 | 'rest_framework_simplejwt.authentication.JWTAuthentication', 159 | ], 160 | } 161 | 162 | #SWAGGER SETTINGS 163 | SWAGGER_SETTINGS = { 164 | 'SECURITY_DEFINITIONS': { 165 | 'api_key': { 166 | 'type': 'apiKey', 167 | 'in': 'header', 168 | 'name': 'Authorization' 169 | } 170 | }, 171 | 'USE_SESSION_AUTH': False, 172 | 'JSON_EDITOR': True, 173 | } 174 | 175 | 176 | #JWT 177 | SIMPLE_JWT = { 178 | "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), 179 | "REFRESH_TOKEN_LIFETIME": timedelta(days=1), 180 | "ROTATE_REFRESH_TOKENS": False, 181 | "BLACKLIST_AFTER_ROTATION": False, 182 | "UPDATE_LAST_LOGIN": False, 183 | 184 | "ALGORITHM": "HS256", 185 | "SIGNING_KEY": "verysecretkey", 186 | 187 | "AUTH_HEADER_TYPES": ("Bearer",), 188 | "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", 189 | "USER_ID_FIELD": "UserID", 190 | "USER_ID_CLAIM": "user_id", 191 | "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule", 192 | 193 | "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",), 194 | "TOKEN_TYPE_CLAIM": "token_type", 195 | "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser", 196 | 197 | "JTI_CLAIM": "jti", 198 | 199 | "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", 200 | "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), 201 | "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), 202 | } -------------------------------------------------------------------------------- /books/views.py: -------------------------------------------------------------------------------- 1 | 2 | from django.shortcuts import render 3 | from rest_framework.generics import GenericAPIView 4 | from rest_framework.response import Response 5 | from rest_framework import status,serializers 6 | from rest_framework.permissions import AllowAny,IsAuthenticated 7 | from books.models import Book, BookDetails,BorrowedBooks 8 | from books.serializers import BookSerializer,BookDetailSerializer,BorrowBookSerializer,BorrowBookReturnSerializer 9 | 10 | # Create your views here. 11 | 12 | #add book 13 | class AddBookView(GenericAPIView): 14 | serializer_class = BookSerializer 15 | def post(self,request): 16 | try: 17 | serializer = BookSerializer(data=request.data) 18 | if serializer.is_valid(): 19 | serializer.save() 20 | return Response(serializer.data, status=status.HTTP_201_CREATED) 21 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 22 | except Exception as e: 23 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 24 | 25 | #get all books 26 | class GetAllBooksView(GenericAPIView): 27 | serializer_class = BookSerializer 28 | def get(self,request): 29 | try: 30 | books=Book.objects.all() 31 | serializer=BookSerializer(books,many=True) 32 | return Response({"Books": serializer.data}, status=status.HTTP_200_OK) 33 | 34 | except Exception as e: 35 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 36 | 37 | #get one book 38 | class GetOneBookView(GenericAPIView): 39 | serializer_class = BookDetailSerializer 40 | def get(self,request,book_id): 41 | try: 42 | books=Book.objects.get(BookID=book_id) 43 | if books: 44 | try: 45 | bookdetail=BookDetails.objects.get(Book_id=books) 46 | except:return Response({"msg":'book details not entered for this ID'}, status=status.HTTP_404_NOT_FOUND) 47 | 48 | if bookdetail: 49 | serializer=BookDetailSerializer(bookdetail) 50 | return Response({"Books": serializer.data}, status=status.HTTP_200_OK) 51 | else: 52 | return Response({"msg":'book not found for the requested ID'}, status=status.HTTP_400_BAD_REQUEST) 53 | 54 | except Exception as e: 55 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 56 | 57 | #create/update existing book 58 | class AssignUpdateBookView(GenericAPIView): 59 | serializer_class = BookDetailSerializer 60 | def post(self,request,book_id): 61 | try: 62 | book=Book.objects.get(BookID=book_id) 63 | if book: 64 | serializer=BookDetailSerializer(data=request.data) 65 | 66 | if serializer.is_valid(raise_exception=True): 67 | serializer.save(Book=book) 68 | return Response(serializer.data, status=status.HTTP_201_CREATED) 69 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 70 | else: 71 | return Response({'msg': 'Book not found from DB'}, status=status.HTTP_404_NOT_FOUND) 72 | except Exception as e: 73 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 74 | 75 | def patch(self,request,book_id): 76 | try: 77 | book=Book.objects.get(BookID=book_id) 78 | if book: 79 | bookdetails=BookDetails.objects.get(Book_id=book_id) 80 | 81 | if bookdetails: 82 | serializer=BookDetailSerializer(bookdetails,data=request.data,partial=True) 83 | 84 | if serializer.is_valid(raise_exception=True): 85 | serializer.save() 86 | return Response(serializer.data, status=status.HTTP_201_CREATED) 87 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 88 | else: 89 | return Response({'msg': 'Book not found from DB'}, status=status.HTTP_404_NOT_FOUND) 90 | except Exception as e: 91 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 92 | 93 | #borrow book 94 | class BorrowBookView(GenericAPIView): 95 | serializer_class = BorrowBookSerializer 96 | def post(self,request): 97 | try: 98 | serializer = BorrowBookSerializer(data=request.data,many=True) 99 | if serializer.is_valid(): 100 | serializer.save() 101 | return Response(serializer.data, status=status.HTTP_201_CREATED) 102 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 103 | 104 | except Exception as e: 105 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 106 | 107 | #return book 108 | class ReturnBookView(GenericAPIView): 109 | serializer_class = BorrowBookReturnSerializer 110 | def post(self,request,borrowed_book_id): 111 | userid=request.data.get('user') 112 | try: 113 | book=Book.objects.get(BookID=borrowed_book_id) 114 | if book: 115 | borrowedbook = BorrowedBooks.objects.get(book_id=borrowed_book_id, user_id=userid,ReturnDate__isnull=True) 116 | if borrowedbook: 117 | borrowedbook.ReturnDate = request.data.get('ReturnDate') 118 | borrowedbook.save() 119 | return Response({'msg': 'Book returned successfully'}, status=status.HTTP_200_OK) 120 | else: 121 | return Response({"msg": "The book is not borrowed by the current user"}, 122 | status=status.HTTP_403_FORBIDDEN) 123 | else: 124 | return Response({"msg":"the book doesnot exist with this ID"}, status=status.HTTP_404_NOT_FOUND) 125 | 126 | except Exception as e: 127 | return Response({'msg': 'Something went wrong', 'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) 128 | 129 | #list all currently borrowed books 130 | class ListAllBorrowedBooksView(GenericAPIView): 131 | serializer_class = BorrowBookSerializer 132 | def get(self, request): 133 | borrowed_books = BorrowedBooks.objects.filter(ReturnDate__isnull=True) 134 | serializer = BorrowBookSerializer(borrowed_books, many=True) 135 | return Response(serializer.data, status=status.HTTP_200_OK) --------------------------------------------------------------------------------