Commit 6c547725 authored by Fahmi's avatar Fahmi

commit

parents
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'
from django.db import models
# Create your models here.
from library.models import *
from .models import *
from rest_framework import serializers
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
class MemberSerializer(serializers.ModelSerializer):
class Meta:
model = Member
fields = '__all__'
class BookLoanSerializer(serializers.ModelSerializer):
class Meta:
model = BookLoan
fields = '__all__'
\ No newline at end of file
from django.test import TestCase
# Create your tests here.
from django.urls import include, path
from api import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('category/', views.CategoryList.as_view()),
path('category/<int:pk>/', views.CategoryDetail.as_view()),
path('book/', views.BookList.as_view()),
path('book/<int:pk>/', views.BookDetail.as_view()),
path('member/', views.MemberList.as_view()),
path('member/<int:pk>/', views.MemberDetail.as_view()),
path('bookloan/', views.BookLoanList.as_view()),
path('bookloan/<int:pk>/', views.BookLoanDetail.as_view()),
]
# urlpatterns = format_suffix_patterns(urlpatterns)
\ No newline at end of file
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from library.models import *
from api.serializers import *
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status, generics
from rest_framework.views import APIView
from django.http import Http404
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
# @csrf_exempt
# @api_view(['GET', 'POST'])
# def book_list(request):
# """
# List all code snippets, or create a new snippet.
# """
# if request.method == 'GET':
# book = Member.objects.all()
# serializer = BookSerializer(book, many=True)
# return Response(serializer.data)
# elif request.method == 'POST':
# data = JSONParser().parse(request)
# serializer = BookSerializer(data=data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# @api_view(['GET', 'PUT', 'DELETE'])
# def book_detail(request, pk):
# """
# Retrieve, update or delete a code snippet.
# """
# try:
# book = Book.objects.get(pk=pk)
# except Book.DoesNotExist:
# return Response(status=status.HTTP_404_NOT_FOUND)
# if request.method == 'GET':
# serializer = BookSerializer(book)
# return Response(serializer.data)
# elif request.method == 'PUT':
# serializer = BookSerializer(book, data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# elif request.method == 'DELETE':
# book.delete()
# return Response(status=status.HTTP_204_NO_CONTENT)
# @csrf_exempt
# @api_view(['GET', 'POST'])
# def member_list(request):
# """
# List all Member, or create a new Member.
# """
# if request.method == 'GET':
# member = Member.objects.all()
# serializer = MemberSerializer(member, many=True)
# return Response(serializer.data)
# elif request.method == 'POST':
# data = JSONParser().parse(request)
# serializer = MemberSerializer(data=data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# @api_view(['GET', 'PUT', 'DELETE'])
# def member_detail(request, pk):
# """
# Retrieve, update or delete a code snippet.
# """
# try:
# member = Member.objects.get(pk=pk)
# except Member.DoesNotExist:
# return Response(status=status.HTTP_404_NOT_FOUND)
# if request.method == 'GET':
# serializer = MemberSerializer(member)
# return Response(serializer.data)
# elif request.method == 'PUT':
# serializer = MemberSerializer(member, data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# elif request.method == 'DELETE':
# member.delete()
# return Response(status=status.HTTP_204_NO_CONTENT)
# class Book_List(APIView):
# """
# List all Book, or create a new Book.
# """
# def get(self, request, format=None):
# book = Book.objects.all()
# serializer = BookSerializer(book, many=True)
# return Response(serializer.data)
# def post(self, request, format=None):
# serializer = BookSerializer(data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# class Book_Detail(APIView):
# """
# Retrieve, update or delete a Book instance.
# """
# def get_object(self, pk):
# try:
# return Book.objects.get(pk=pk)
# except Book.DoesNotExist:
# raise Http404
# def get(self, request, pk, format=None):
# book = self.get_object(pk)
# serializer = BookSerializer(book)
# return Response(serializer.data)
# def put(self, request, pk, format=None):
# book = self.get_object(pk)
# serializer = BookSerializer(book, data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# def delete(self, request, pk, format=None):
# book = self.get_object(pk)
# book.delete()
# return Response(status=status.HTTP_204_NO_CONTENT)
# class Member_List(APIView):
# """
# List all Member, or create a new Member.
# """
# def get(self, request, format=None):
# member = Member.objects.all()
# serializer = MemberSerializer(member, many=True)
# return Response(serializer.data)
# def post(self, request, format=None):
# serializer = MemberSerializer(data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# class Member_Detail(APIView):
# """
# Retrieve, update or delete a Member instance.
# """
# def get_object(self, pk):
# try:
# return Member.objects.get(pk=pk)
# except Member.DoesNotExist:
# raise Http404
# def get(self, request, pk, format=None):
# member = self.get_object(pk)
# serializer = MemberSerializer(member)
# return Response(serializer.data)
# def put(self, request, pk, format=None):
# member = self.get_object(pk)
# serializer = MemberSerializer(member, data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# def delete(self, request, pk, format=None):
# member = self.get_object(pk)
# member.delete()
# return Response(status=status.HTTP_204_NO_CONTENT)
# class BookLoan_List(APIView):
# """
# List all BookLoan, or create a new BookLoan.
# """
# def get(self, request, format=None):
# bookloan = BookLoan.objects.all()
# serializer = BookLoanSerializer(bookloan, many=True)
# return Response(serializer.data)
# def post(self, request, format=None):
# serializer = BookLoanSerializer(data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CategoryList(generics.ListCreateAPIView):
queryset = Category.objects.all()
serializer_class = CategorySerializer
class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Category.objects.all()
serializer_class = CategorySerializer
class BookList(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class MemberList(generics.ListCreateAPIView):
queryset = Member.objects.all()
serializer_class = MemberSerializer
class MemberDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Member.objects.all()
serializer_class = MemberSerializer
class BookLoanList(generics.ListCreateAPIView):
queryset = BookLoan.objects.all()
serializer_class = BookLoanSerializer
pagination_class = MyPageNumberPagination
class BookLoanDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = BookLoan.objects.all()
serializer_class = BookLoanSerializer
\ No newline at end of file
File added
"""
ASGI config for djangoproj project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoproj.settings')
application = get_asgi_application()
"""
Django settings for djangoproj project.
Generated by 'django-admin startproject' using Django 4.2.8.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-suaet%v3@p8i7&8z29^n0vq9tc=+qb@$azkes2fs^q3o#6y_&q'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'library',
'api',
'rest_framework',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'djangoproj.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'djangoproj.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Jakarta'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_URL='/login'
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 5
}
\ No newline at end of file
"""
URL configuration for djangoproj project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/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, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("library.urls")),
path('api/', include('api.urls')),
]
"""
WSGI config for djangoproj project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoproj.settings')
application = get_wsgi_application()
from django.contrib import admin
from .models import Book, Member, BookLoan, Librarian, LoginHistory
admin.site.register(Book)
admin.site.register(Member)
admin.site.register(BookLoan)
admin.site.register(Librarian)
admin.site.register(LoginHistory)
\ No newline at end of file
from django.apps import AppConfig
class LibraryConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'library'
from imaplib import _Authenticator
from django import forms
from .models import Book, Category, Member, BookLoan, Librarian
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
class LoginForm(forms.Form):
username = forms.CharField(max_length=50)
password = forms.CharField(widget=forms.PasswordInput)
# class RegistrationForm(UserCreationForm):
# email = forms.EmailField(required=True)
# class Meta:
# model = User
# fields = ['username', 'email', 'password1', 'password2']
# def clean_email(self):
# email = self.cleaned_data['email']
# if User.objects.filter(email=email).exists():
# raise forms.ValidationError("Email is already in use.")
# return email
# def clean(self):
# cleaned_data = super().clean()
# password1 = cleaned_data.get('password1')
# password2 = cleaned_data.get('password2')
# if password1 and password2 and password1 != password2:
# raise forms.ValidationError('Passwords do not match')
# return cleaned_data
# class UserCreationForm(UserCreationForm):
# class Meta:
# model = User
# fields = UserCreationForm.Meta.fields + 'email'
class userCreat(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class LibrarianForm(forms.ModelForm):
class Meta:
model = Librarian
fields = ['name']
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# self.fields.update(UserCreationForm.base_fields)
# def is_valid(self):
# return super().is_valid() and UserCreationForm(self.cleaned_data).is_valid()
# def save(self, commit=True):
# user = UserCreationForm(self.cleaned_data).save(commit=False)
# user.save()
# librarian = super().save(commit=False)
# librarian.user = user
# if commit:
# librarian.save()
# return librarian
class LibrarianUpdateForm(UserChangeForm):
name = forms.CharField(max_length=100)
class Meta:
model = User
fields = ['username', 'email', 'name']
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'publisher', 'isbn']
class MemberForm(forms.ModelForm):
class Meta:
model = Member
fields = ['name', 'address', 'email', 'phone_number']
class BookLoanForm(forms.ModelForm):
book = forms.ModelChoiceField(queryset=Book.objects.all(), label='Book')
member = forms.ModelChoiceField(queryset=Member.objects.all(), label='Member')
class Meta:
model = BookLoan
fields = ['book', 'member', 'due_date', 'return_date', 'is_returned']
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['name']
# Generated by Django 4.2.8 on 2023-12-19 07:31
from django.db import migrations, models
import django.db.models.deletion
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=100)),
('author', models.CharField(max_length=100)),
('publisher', models.CharField(max_length=100)),
('isbn', models.CharField(max_length=13, unique=True)),
],
),
migrations.CreateModel(
name='Librarian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('username', models.CharField(max_length=50, unique=True)),
('password', models.CharField(max_length=100)),
('email', models.EmailField(max_length=254, unique=True)),
],
),
migrations.CreateModel(
name='Member',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('address', models.TextField()),
('email', models.EmailField(max_length=254, unique=True)),
('phone_number', models.CharField(max_length=15)),
],
),
migrations.CreateModel(
name='LoginHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('login_time', models.DateTimeField()),
('logout_time', models.DateTimeField(blank=True, null=True)),
('librarian', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.librarian')),
],
),
migrations.CreateModel(
name='BookLoan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('loan_date', models.DateField(auto_now_add=True)),
('due_date', models.DateField()),
('return_date', models.DateField(blank=True, null=True)),
('is_returned', models.BooleanField(default=False)),
('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.book')),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.member')),
],
),
]
# Generated by Django 4.2.8 on 2023-12-20 02:43
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('library', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='librarian',
name='email',
),
migrations.RemoveField(
model_name='librarian',
name='password',
),
migrations.RemoveField(
model_name='librarian',
name='username',
),
migrations.AddField(
model_name='librarian',
name='user',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 4.2.8 on 2023-12-20 04:19
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('library', '0002_remove_librarian_email_remove_librarian_password_and_more'),
]
operations = [
migrations.RemoveField(
model_name='loginhistory',
name='logout_time',
),
migrations.AlterField(
model_name='loginhistory',
name='librarian',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='loginhistory',
name='login_time',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]
# Generated by Django 4.2.8 on 2023-12-22 06:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0003_remove_loginhistory_logout_time_and_more'),
]
operations = [
migrations.AddField(
model_name='bookloan',
name='is_late',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='bookloan',
name='late_fee',
field=models.IntegerField(default=0),
),
]
# Generated by Django 4.2.8 on 2023-12-22 06:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('library', '0004_bookloan_is_late_bookloan_late_fee'),
]
operations = [
migrations.RemoveField(
model_name='bookloan',
name='is_late',
),
]
# Generated by Django 4.2.8 on 2023-12-22 06:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('library', '0005_remove_bookloan_is_late'),
]
operations = [
migrations.RemoveField(
model_name='bookloan',
name='late_fee',
),
]
# Generated by Django 4.2.8 on 2023-12-27 10:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0006_remove_bookloan_late_fee'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
],
),
]
# Generated by Django 4.2.8 on 2023-12-28 03:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('library', '0007_category'),
]
operations = [
migrations.AddField(
model_name='book',
name='category',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='library.category'),
preserve_default=False,
),
]
# Generated by Django 4.2.8 on 2023-12-28 06:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0008_book_category'),
]
operations = [
migrations.AddField(
model_name='book',
name='date_publish',
field=models.DateField(null=True),
),
]
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
publisher = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date_publish = models.DateField(null=True)
isbn = models.CharField(max_length=13, unique=True)
def __str__(self):
return self.title
class Member(models.Model):
name = models.CharField(max_length=100)
address = models.TextField()
email = models.EmailField(unique=True)
phone_number = models.CharField(max_length=15)
def __str__(self):
return self.name
class BookLoan(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
loan_date = models.DateField(auto_now_add=True)
due_date = models.DateField()
return_date = models.DateField(null=True, blank=True)
is_returned = models.BooleanField(default=False)
def __str__(self):
return f"{self.book.title} - {self.member.name}"
class Librarian(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
@receiver(user_logged_in, sender=User)
def create_librarian_login_history(sender, user, **kwargs):
LoginHistory.objects.create(librarian=user)
class LoginHistory(models.Model):
librarian = models.ForeignKey(User, on_delete=models.CASCADE)
login_time = models.DateTimeField(default=timezone.now)
def __str__(self):
return f'{self.librarian.username} - {self.login_time}'
\ No newline at end of file
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Area Chart Example
var ctx = document.getElementById("myAreaChart");
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"],
datasets: [{
label: "Sessions",
lineTension: 0.3,
backgroundColor: "rgba(2,117,216,0.2)",
borderColor: "rgba(2,117,216,1)",
pointRadius: 5,
pointBackgroundColor: "rgba(2,117,216,1)",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(2,117,216,1)",
pointHitRadius: 50,
pointBorderWidth: 2,
data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451],
}],
},
options: {
scales: {
xAxes: [{
time: {
unit: 'date'
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 7
}
}],
yAxes: [{
ticks: {
min: 0,
max: 40000,
maxTicksLimit: 5
},
gridLines: {
color: "rgba(0, 0, 0, .125)",
}
}],
},
legend: {
display: false
}
}
});
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Bar Chart Example
var ctx = document.getElementById("myBarChart");
var myLineChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
label: "Revenue",
backgroundColor: "rgba(2,117,216,1)",
borderColor: "rgba(2,117,216,1)",
data: [4215, 5312, 6251, 7841, 9821, 14984],
}],
},
options: {
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 6
}
}],
yAxes: [{
ticks: {
min: 0,
max: 15000,
maxTicksLimit: 5
},
gridLines: {
display: true
}
}],
},
legend: {
display: false
}
}
});
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Pie Chart Example
var ctx = document.getElementById("myPieChart");
var myPieChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["Blue", "Red", "Yellow", "Green"],
datasets: [{
data: [12.21, 15.58, 11.25, 8.32],
backgroundColor: ['#007bff', '#dc3545', '#ffc107', '#28a745'],
}],
},
});
// Call the dataTables jQuery plugin
$(document).ready(function() {
$('#dataTable').DataTable();
});
This diff is collapsed.
window.addEventListener('DOMContentLoaded', event => {
// Simple-DataTables
// https://github.com/fiduswriter/Simple-DataTables/wiki
const datatablesSimple = document.getElementById('datatablesSimple');
if (datatablesSimple) {
new simpleDatatables.DataTable(datatablesSimple);
}
});
/*!
* Start Bootstrap - SB Admin v7.0.7 (https://startbootstrap.com/template/sb-admin)
* Copyright 2013-2023 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin/blob/master/LICENSE)
*/
//
// Scripts
//
window.addEventListener('DOMContentLoaded', event => {
// Toggle the side navigation
const sidebarToggle = document.body.querySelector('#sidebarToggle');
if (sidebarToggle) {
// Uncomment Below to persist sidebar toggle between refreshes
// if (localStorage.getItem('sb|sidebar-toggle') === 'true') {
// document.body.classList.toggle('sb-sidenav-toggled');
// }
sidebarToggle.addEventListener('click', event => {
event.preventDefault();
document.body.classList.toggle('sb-sidenav-toggled');
localStorage.setItem('sb|sidebar-toggle', document.body.classList.contains('sb-sidenav-toggled'));
});
}
});
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Library Web</title>
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" />
<link href="{% static 'css/styles.css' %}" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<!-- Navbar Brand-->
<a class="navbar-brand ps-3" href="{% url 'homepage' %}">Library Web</a>
<button class="btn btn-link btn-sm order-1 order-lg-0 me-4 me-lg-0" id="sidebarToggle" href="#!"><i class="fas fa-bars"></i></button>
<!-- Navbar Search-->
<form class="d-none d-md-inline-block form-inline ms-auto me-0 me-md-3 my-2 my-md-0">
</form>
<ul class=" navbar-nav ms-auto ms-md-0 me-3 me-lg-4">
<li class="nav-item dropdown">
{% if request.user.is_authenticated %}
<a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fas fa-user fa-fw"></i>{{request.user.username}}</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item">{{request.user.username}}</a></li>
<li><a class="dropdown-item" href="{% url 'logout' %}">Logout</a></li>
</ul>
{% endif %}
</li>
</ul>
</nav>
<div id="layoutSidenav">
<div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu">
<div class="nav">
{% if request.user.is_authenticated %}
<a class="nav-link" href="{% url 'dashboard' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
dashboard
</a>
<a class="nav-link" href="{% url 'book_list' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Book List
</a>
<a class="nav-link" href="{% url 'member_list' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Member List
</a>
<a class="nav-link" href="{% url 'book_loan_list' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Book Loan List
</a>
<a class="nav-link" href="{% url 'librarian_list' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Librarian List
</a>
<a class="nav-link" href="{% url 'category_list' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Category
</a>
{%else %}
<a class="nav-link" href="{% url 'login' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-columns"></i></div>
Log in
</a>
<a class="nav-link" href="{% url 'register' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-columns"></i></div>
register
</a>
{% endif %}
</div>
</div>
</nav>
</div>
<div id="layoutSidenav_content">
{% block content%}
{% endblock content%}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="{% static 'js/scripts.js' %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src="{% static 'assets/demo/chart-area-demo.js' %}"></script>
<script src="{% static 'assets/demo/chart-bar-demo.js' %}"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="{% static 'js/datatables-simple-demo.js' %}"></script>
</body>
</html>
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Book List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Title</th>
<th>Author</th>
<th>Publisher</th>
<th>ISBN</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Title</th>
<th>Author</th>
<th>Publisher</th>
<th>ISBN</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.author }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.isbn }}</td>
<td>
<a class="btn btn-secondary col-2 mx-2" href="edit/{{book.id}}" role="button">Edit</a>
<a class="btn btn-danger col-3 mx-2" href="delete/{{book.id}}" role="button" onclick="return confirm('Are you sure you want to delete {{book.title}}?')">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
<a class="btn btn-primary col-1 mx-3" href="{% url 'book-new' %}" role="button">Add Book</a>
</div>
</div>
</div>
</div>
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Book Loan List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead>
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</tfoot>
<tbody>
{% for book_loan in book_loan %}
<tr>
<td>{{ book_loan.book.title }}</td>
<td>{{ book_loan.member.name }}</td>
<td>{{ book_loan.loan_date }}</td>
<td>{{ book_loan.due_date }}</td>
<td>{{ book_loan.return_date|default:"Not Returned" }}</td>
<td>{% if book_loan.is_returned %}Returned{% else %}Not Returned{% endif %}</td>
<td>
<a class="btn btn-secondary col-3 mx-2" href="{% url 'book_loan_edit' id=book_loan.id %}" role="button">Edit</a>
<a class="btn btn-danger col-3 mx-2" href="delete/{{book_loan.id}}" role="button" onclick="return confirm('Are you sure you want to delete?')">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
<a class="btn btn-primary col-2 mx-3" href="{% url 'book_loan_new' %}" role="button">Add Book Loan</a>
<a class="btn btn-primary col-2 mx-3" href="{% url 'near_outstanding_loans' %}" role="button">Outstanding Book Loan</a>
<a class="btn btn-primary col-2 mx-3" href="{% url 'overdue_loans' %}" role="button">Overdue Book Loan</a>
</div>
</div>
</div>
</div>
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Add Book Loan</div>
<div class="card-body">
<form method="post" action="{% url 'book_loan_new' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_book">Book:</label>
<select name="book" id="id_book" class="form-control" required>
{% for book in books %}
<option value="{{ book.id }}">{{ book.title }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="id_member">Member:</label>
<select name="member" id="id_member" class="form-control" required>
{% for member in members %}
<option value="{{ member.id }}">{{ member.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="id_due_date">Due Date:</label>
<input type="date" name="due_date" id="id_due_date" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Add Book Loan</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Add Book Loan</h2>
<form method="post" action="{% url 'book_loan_new' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<!-- <div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Edit Book Loan</div>
<div class="card-body">
<form method="post" action="{% url 'book_loan_edit' id=book_loan.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="book_title">Book Title:</label>
<p>{{ book_loan.book.title }}</p>
</div>
<div class="mb-3">
<label for="member_name">Member Name:</label>
<p>{{ book_loan.member.name }}</p>
</div>
<div class="mb-3">
<label for="due_date">Due Date:</label>
<input type="date" name="due_date" id="due_date" value="{{ book_loan.due_date }}" class="form-control"required>
</div>
<div class="mb-3">
<label for="return_date">Return Date:</label>
<input type="date" name="return_date" id="return_date" value="{{ book_loan.return_date }}" class="form-control">
</div>
<div class="mb-3">
<label for="is_returned">Is Returned:</label>
<input type="checkbox" name="is_returned" id="is_returned" class="form-check-input" {% if book_loan.is_returned %}checked{% endif %}>
</div>
<button type="submit" class="btn btn-primary" role="button">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
</div> -->
<div style="text-align: center; margin-top: 50px;">
<h2>Edit Book Loan</h2>
<form method="post" action="{% url 'book_loan_edit' id=book_loan.id %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
{% endblock content %}
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Add Book</div>
<div class="card-body">
<form method="post" action="{% url 'book-new' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_title" class="form-label">Book Title</label>
<input type="text" name="title" id="id_title" placeholder="Book Title" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_author" class="form-label">Author</label>
<input type="text" name="author" id="id_author" placeholder="Author" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_publisher" class="form-label">Publisher</label>
<input type="text" name="publisher" id="id_publisher" placeholder="Publisher" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_isbn" class="form-label">ISBN</label>
<input type="text" name="isbn" id="id_isbn" placeholder="ISBN" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Add</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Add Book</h2>
<form method="post" action="{% url 'book_new' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Edit Book</div>
<div class="card-body">
<form method="post" action="{% url 'edit_book' id=book.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_title" class="form-label">Book Title</label>
<input type="text" name="title" id="id_title" value="{{ book.title }}" placeholder="Book Title" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_author" class="form-label">Author</label>
<input type="text" name="author" id="id_author" value="{{ book.author }}" placeholder="Author" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_publisher" class="form-label">Publisher</label>
<input type="text" name="publisher" id="id_publisher" value="{{ book.publisher }}" placeholder="Publisher" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_isbn" class="form-label">ISBN</label>
<input type="text" name="isbn" id="id_isbn" value="{{ book.isbn }}" placeholder="ISBN" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Category List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Name</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
</tr>
</tfoot>
<tbody>
{% for category in categories %}
<tr>
<td>{{ category.name }}</td>
<td>
<a class="btn btn-secondary col-2 mx-2" href="{% url 'librarian_edit' pk=librarian.pk %}" role="button">Edit</a>
<a class="btn btn-danger col-2 mx-2" href="delete/{{librarian.id}}" role="button" onclick="return confirm('Are you sure you want to delete {{book.title}}?')">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
<a class="btn btn-primary col-2 mx-3" href="{% url 'librarian_new' %}" role="button">Add a Librarian</a>
<a class="btn btn-primary col-2 mx-3" href="{% url 'librarian_login_history' %}" role="button">Librarian Login History</a>
</div>
</div>
</div>
</div>
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div style="text-align: center; margin-top: 50px;">
<h2>Add Category</h2>
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
{% endblock content %}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div style="text-align: center; margin-top: 50px;">
<h2>Add Category</h2>
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
{% endblock content %}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-3">
<h2 style="text-align: center;" font-family: serif;>Welcome to the Librarian Dashboard!</h2>
</div>
{% load static %}
<img src="{% static 'assets/perpustakaan.jpg' %}" class="img-fluid" alt="Perpustakaan">
{% endblock %}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<h2 style="text-align: center;" font-family: serif;>Welcome to the Library Homepage!</h2>
</div>
{% load static %}
<img src="{% static 'assets/perpustakaan.jpg' %}" alt="Perpustakaan">
<p style="text-align: center;" font-family: serif>This is a simple homepage for our library website.</p>
{% endblock content%}
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Dashboard - SB Admin</title>
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" />
<link href="{% static 'css/styles.css' %}" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<!-- Navbar Brand-->
<a class="navbar-brand ps-3" href="index.html">Start Bootstrap</a>
<!-- Sidebar Toggle-->
<button class="btn btn-link btn-sm order-1 order-lg-0 me-4 me-lg-0" id="sidebarToggle" href="#!"><i class="fas fa-bars"></i></button>
<!-- Navbar Search-->
<form class="d-none d-md-inline-block form-inline ms-auto me-0 me-md-3 my-2 my-md-0">
<div class="input-group">
<input class="form-control" type="text" placeholder="Search for..." aria-label="Search for..." aria-describedby="btnNavbarSearch" />
<button class="btn btn-primary" id="btnNavbarSearch" type="button"><i class="fas fa-search"></i></button>
</div>
</form>
<!-- Navbar-->
<ul class="navbar-nav ms-auto ms-md-0 me-3 me-lg-4">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fas fa-user fa-fw"></i></a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#!">Settings</a></li>
<li><a class="dropdown-item" href="#!">Activity Log</a></li>
<li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="#!">Logout</a></li>
</ul>
</li>
</ul>
</nav>
<div id="layoutSidenav">
<div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu">
<div class="nav">
<div class="sb-sidenav-menu-heading">Core</div>
<a class="nav-link" href="index.html">
<div class="sb-nav-link-icon"><i class="fas fa-tachometer-alt"></i></div>
Dashboard
</a>
<div class="sb-sidenav-menu-heading">Interface</div>
<a class="nav-link collapsed" href="#" data-bs-toggle="collapse" data-bs-target="#collapseLayouts" aria-expanded="false" aria-controls="collapseLayouts">
<div class="sb-nav-link-icon"><i class="fas fa-columns"></i></div>
Layouts
<div class="sb-sidenav-collapse-arrow"><i class="fas fa-angle-down"></i></div>
</a>
<div class="collapse" id="collapseLayouts" aria-labelledby="headingOne" data-bs-parent="#sidenavAccordion">
<nav class="sb-sidenav-menu-nested nav">
<a class="nav-link" href="layout-static.html">Static Navigation</a>
<a class="nav-link" href="layout-sidenav-light.html">Light Sidenav</a>
</nav>
</div>
<a class="nav-link collapsed" href="#" data-bs-toggle="collapse" data-bs-target="#collapsePages" aria-expanded="false" aria-controls="collapsePages">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Pages
<div class="sb-sidenav-collapse-arrow"><i class="fas fa-angle-down"></i></div>
</a>
<div class="collapse" id="collapsePages" aria-labelledby="headingTwo" data-bs-parent="#sidenavAccordion">
<nav class="sb-sidenav-menu-nested nav accordion" id="sidenavAccordionPages">
<a class="nav-link collapsed" href="#" data-bs-toggle="collapse" data-bs-target="#pagesCollapseAuth" aria-expanded="false" aria-controls="pagesCollapseAuth">
Authentication
<div class="sb-sidenav-collapse-arrow"><i class="fas fa-angle-down"></i></div>
</a>
<div class="collapse" id="pagesCollapseAuth" aria-labelledby="headingOne" data-bs-parent="#sidenavAccordionPages">
<nav class="sb-sidenav-menu-nested nav">
<a class="nav-link" href="login.html">Login</a>
<a class="nav-link" href="register.html">Register</a>
<a class="nav-link" href="password.html">Forgot Password</a>
</nav>
</div>
<a class="nav-link collapsed" href="#" data-bs-toggle="collapse" data-bs-target="#pagesCollapseError" aria-expanded="false" aria-controls="pagesCollapseError">
Error
<div class="sb-sidenav-collapse-arrow"><i class="fas fa-angle-down"></i></div>
</a>
<div class="collapse" id="pagesCollapseError" aria-labelledby="headingOne" data-bs-parent="#sidenavAccordionPages">
<nav class="sb-sidenav-menu-nested nav">
<a class="nav-link" href="401.html">401 Page</a>
<a class="nav-link" href="404.html">404 Page</a>
<a class="nav-link" href="500.html">500 Page</a>
</nav>
</div>
</nav>
</div>
<div class="sb-sidenav-menu-heading">Addons</div>
<a class="nav-link" href="charts.html">
<div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div>
Charts
</a>
<a class="nav-link" href="tables.html">
<div class="sb-nav-link-icon"><i class="fas fa-table"></i></div>
Tables
</a>
</div>
</div>
</nav>
</div>
<div id="layoutSidenav_content">
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="{% static 'js/scripts.js' %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src="{% static 'assets/demo/chart-area-demo.js' %}"></script>
<script src="{% static 'assets/demo/chart-bar-demo.js' %}"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="{% static 'js/datatables-simple-demo.js' %}"></script>
</body>
</html>
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Member List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Name</th>
<th>Username</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Username</th>
<th>Email</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
{% for librarian in librarian %}
<tr>
<td>{{ librarian.name }}</td>
<td>{{ librarian.user.username }}</td>
<td>{{ librarian.user.email }}</td>
<td>
<a class="btn btn-secondary col-2 mx-2" href="{% url 'librarian_edit' pk=librarian.pk %}" role="button">Edit</a>
<a class="btn btn-danger col-2 mx-2" href="delete/{{librarian.id}}" role="button" onclick="return confirm('Are you sure you want to delete {{book.title}}?')">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
<a class="btn btn-primary col-2 mx-3" href="{% url 'librarian_new' %}" role="button">Add a Librarian</a>
<a class="btn btn-primary col-2 mx-3" href="{% url 'librarian_login_history' %}" role="button">Librarian Login History</a>
</div>
</div>
</div>
</div>
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Librarian Login History List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Librarian</th>
<th>Login Time</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Librarian</th>
<th>Login Time</th>
</tfoot>
<tbody>
{% for entry in login_history %}
<tr>
<td>{{ entry.librarian.username }}</td>
<td>{{ entry.login_time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Add Librarian</div>
<div class="card-body">
<form method="post" action="{% url 'librarian_new' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name">Name:</label>
<input type="text" name="name" id="id_name" placeholder="Input Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_username">Username:</label>
<input type="text" name="username" id="id_username" placeholder="Username" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_email">Email:</label>
<input type="email" name="email" id="id_email" placeholder="Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password">Password:</label>
<input type="password" name="password1" id="id_password" placeholder="Password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password2">Confirm Password:</label>
<input type="password" name="password2" id="id_password2" placeholder="Confirm Password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Add Librarian</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <script>
function validateForm() {
var password = document.getElementById("id_password").value;
var confirmPassword = document.getElementById("id_confirm_password").value;
if (password !== confirmPassword) {
alert("Passwords do not match.");
return false;
}
return true;
}
</script> -->
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Add Librarian</h2>
<form method="post" action="{% url 'librarian_new' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Edit Librarian</div>
<div class="card-body">
<form method="post" action="{% url 'librarian_edit' pk=librarian.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name">Name:</label>
<input type="text" name="name" id="id_name" value="{{ librarian.name }}" placeholder="Input Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_username">Username:</label>
<input type="text" name="username" id="id_username" value="{{ librarian.user.username }}" placeholder="Username" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_email">Email:</label>
<input type="email" name="email" id="id_email" value="{{ librarian.user.email }}" placeholder="Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password">New Password:</label>
<input type="password" name="password1" id="id_password" placeholder="Password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password2">Confirm Password:</label>
<input type="password" name="password2" id="id_password2" placeholder="Confirm Password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content%}
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Edit Librarian</h2>
<form method="post" action="{% url 'librarian_edit' pk=librarian.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name">Name:</label>
<input type="text" name="name" id="id_name" value="{{ librarian.name }}" placeholder="Input Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_username">Username:</label>
<input type="text" name="username" id="id_username" value="{{ librarian.user.username }}" placeholder="Username" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_email">Email:</label>
<input type="email" name="email" id="id_email" value="{{ librarian.user.email }}" placeholder="Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password">Password:</label>
<input type="password" name="password1" id="id_password" placeholder="Password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password2">Confirm Password:</label>
<input type="password" name="password2" id="id_password2" placeholder="Confirm Password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Login</div>
<div class="card-body">
{% if user.is_authenticated %}
<meta http-equiv="refresh" content="0; url={% url 'dashboard' %}" />
{% else %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_username" class="form-label">Username</label>
<input type="text" name="username" id="id_username" placeholder="Username" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password" class="form-label">Password</label>
<input type="password" name="password" id="id_password" placeholder="Password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Login</button>
</form>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Member List
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr class="bg-danger">
<th>Name</th>
<th>Email</th>
<th>Address</th>
<th>Phone Number</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Email</th>
<th>Address</th>
<th>Phone Number</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
{% for member in members %}
<tr>
<td>{{ member.name }}</td>
<td>{{ member.email }}</td>
<td>{{ member.address }}</td>
<td>{{ member.phone_number }}</td>
<td>
<a class="btn btn-secondary col-3 mx-2" href="edit/{{member.id}}" role="button">Edit</a>
<a class="btn btn-danger col-3 mx-2" href="delete/{{member.id}}" role="button" onclick="return confirm('Are you sure you want to delete {{ member.name }}')">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
<a class="btn btn-primary col-1 mx-3" href="{% url 'member_new' %}" role="button">Add Member</a>
</div>
</div>
</div>
</div>
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Add Member</div>
<div class="card-body">
<form method="post" action="{% url 'member_new' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name" class="form-label">Name</label>
<input type="text" name="name" id="id_name" placeholder="Input Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_email" class="form-label">Email</label>
<input type="email" name="email" id="id_email" placeholder="Input Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_address" class="form-label">Address</label>
<input type="text" name="address" id="id_address" placeholder="Input Address" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_phone_number" class="form-label">Phone Number</label>
<input type="tel" name="phone_number" id="id_phone_number" placeholder="Phone Number" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Add</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Add Member</h2>
<form method="post" action="{% url 'member_new' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
\ No newline at end of file
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Edit Member</div>
<div class="card-body">
<form method="post" action="{% url 'edit_member' id=member.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name" class="form-label">Name</label>
<input type="text" name="name" id="id_name" value="{{ member.name }}" placeholder="Input Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_email" class="form-label">Email</label>
<input type="email" name="email" id="id_email" value="{{ member.email }}" placeholder="Input Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_address" class="form-label">Address</label>
<input type="text" name="address" id="id_address" value="{{ member.address }}" placeholder="Input Address" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_phone_number" class="form-label">Phone Number</label>
<input type="tel" name="phone_number" id="id_phone_number" value="{{ member.phone_number }}" placeholder="Phone Number" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Add Member</h2>
<form method="post" action="{% url 'edit_member' id=member.id %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Near Outstanding Book Loans
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Remaining Days</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Remaining Days</th>
</tr>
</tfoot>
<tbody>
{% for loan in near_outstanding_loan %}
<tr>
<td>{{ loan.book.title }}</td>
<td>{{ loan.member.name }}</td>
<td>{{ loan.loan_date }}</td>
<td>{{ loan.due_date }}</td>
<td>{{ loan.time_difference.days }} Days</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-2">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-table me-1"></i>
Overdue Book Loans
</div>
<div class="card-body">
<table id="datatablesSimple">
<thead >
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Overdue Date</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Book Title</th>
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Overdue Date</th>
</tr>
</tfoot>
<tbody>
{% for loan in over_due %}
<tr>
<td>{{ loan.book.title }}</td>
<td>{{ loan.member.name }}</td>
<td>{{ loan.loan_date }}</td>
<td>{{ loan.due_date }}</td>
<td>{{ loan.return_date }}</td>
<td>{{ loan.dead.days}} Days</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
{% extends 'base.html' %}
{% block content%}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Create Account</div>
<div class="card-body">
<form method="post" action="{% url 'register' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name" class="form-label">Name</label>
<input type="text" name="name" id="id_name" placeholder="Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_username" class="form-label">Username</label>
<input type="text" name="username" id="id_username" placeholder="Username" class="form-control" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" name="email" id="email" placeholder="Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password1" class="form-label">Password</label>
<input type="password" name="password1" id="id_password1" placeholder="Password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_password2" class="form-label">Password</label>
<input type="password" name="password2" id="id_password2" placeholder="Confirm Password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Create</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Create Account</h2>
<form method="post" action="{% url 'register' %}">
{% csrf_token %}
{{ user_form.as_p }}
{{ librarian_form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
This diff is collapsed.
from django.test import TestCase
# Create your tests here.
from django.urls import path
from django.contrib.auth.views import LogoutView
from .views import *
from django.views.generic import TemplateView, ListView
urlpatterns = [
path('', homepage, name='homepage'),
path('login/', login_view, name='login'),
path('logout/', LogoutView.as_view(next_page='homepage'), name='logout'),
path('register/', register_view, name='register'),
path('dashboard/', dashboard, name='dashboard'),
path('librarians/', librarian_list, name='librarian_list'),
path('librarians/add/', librarian_new, name='librarian_new'),
path('librarians/edit/<int:pk>/', librarian_update, name='librarian_edit'),
path('librarians/delete/<int:pk>/', librarian_delete, name='librarian_delete'),
path('books/', book_list, name='book_list'),
path('books/add/', book_new, name='book_new'),
path('books/edit/<int:id>/', book_update, name='edit_book'),
path('books/delete/<int:id>/', book_delete, name='delete_book'),
path('book-loans/', book_loan_list, name='book_loan_list'),
path('book-loans/add/', book_loan_new, name='book_loan_new'),
path('book-loans/edit/<int:id>/', book_loan_update, name='book_loan_edit'),
# path('book-loans/edit/<str:pk>/', book_loan_update, name='book_loan_edit'),
# path('book-loans/edit/<uuid:pk>/', book_loan_update, name='book_loan_edit'),
path('book-loans/delete/<int:id>/', book_loan_delete, name='book_loan_delete'),
path('near-outstanding-loans/', near_outstanding_loans, name='near_outstanding_loans'),
path('overdue-loans/', overdue_loans, name='overdue_loans'),
path('member/', member_list, name='member_list'),
path('member/add/', member_new, name='member_new'),
path('member/edit/<int:id>/', edit_member, name='edit_member'),
path('member/delete/<int:id>', delete_member, name='delete_member'),
path('librarian-login-history/', librarian_login_history, name='librarian_login_history'),
path("books2/", BookList.as_view(), name='book-list'),
path("books2/add/", BookCreateView.as_view(), name='book-new'),
path('categories/', CategoryListView.as_view(), name='category_list'),
]
\ No newline at end of file
from django.conf import settings
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import authenticate, login
from django.contrib.auth.views import LogoutView
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from datetime import date, timedelta
from django.db.models import F, ExpressionWrapper, fields
from django.urls import reverse_lazy
from .forms import *
from .models import Book, Member, BookLoan, Librarian, LoginHistory
from django.views.generic import *
# Create your views here.
def homepage(request):
return render(request, 'homepage.html')
def login_view(request):
login_form = LoginForm()
if request.method == 'POST':
login_form = LoginForm(request.POST)
if login_form.is_valid():
username = login_form.cleaned_data['username']
password = login_form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return redirect('dashboard')
else:
login_form.add_error(None, 'Invalid username or password')
return render(request, 'login.html', {'login_form': login_form})
def register_view(request):
if request.method == 'POST':
user_form = userCreat(request.POST)
librarian_form = LibrarianForm(request.POST)
if user_form.is_valid() and librarian_form.is_valid():
user = user_form.save()
librarian = librarian_form.save(commit=False)
librarian.user = user
librarian.save()
return redirect('login')
else:
user_form = UserCreationForm()
librarian_form = LibrarianForm()
context = {'user_form': user_form, 'librarian_form': librarian_form}
return render(request, 'register.html', context)
@login_required
def dashboard(request):
return render(request, 'dashboard.html')
@login_required
class CustomLogoutView(LogoutView):
next_page = 'homepage'
@login_required
def book_list(request):
books = Book.objects.all()
return render(request, 'book_list.html', {'books': books})
@login_required
def book_new(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save()
return redirect('book_list')
else:
form = BookForm()
return render(request, 'book_new.html', {'form': form})
@login_required
def book_update(request, id):
context = {}
book = get_object_or_404(Book, id=id)
form = BookForm(instance=book)
context['book'] = book
if request.method == 'POST':
form = BookForm(request.POST, instance=book)
if form.is_valid():
form.save()
return redirect('book_list')
else:
form = BookForm(instance=book)
context['form'] = form
return render(request, 'book_update.html', context)
@login_required
def book_delete(request, id):
book = get_object_or_404(Book, id=id)
book.delete()
return redirect('book_list')
@login_required
def member_list(request):
members = Member.objects.all()
return render(request, 'member_list.html', {'members': members})
@login_required
def member_new(request):
if request.method == 'POST':
form = MemberForm(request.POST)
if form.is_valid():
form.save()
return redirect('member_list')
else:
form = MemberForm()
return render(request, 'member_new.html', {'form': form})
@login_required
def edit_member(request, id):
context = {}
member = get_object_or_404(Member, id=id)
form = MemberForm(instance=member)
context['member'] = member
if request.method == 'POST':
form = MemberForm(request.POST, instance=member)
if form.is_valid():
form.save()
return redirect(member_list)
else:
form = MemberForm(instance=member)
context['form'] = form
return render(request, 'member_update.html', context)
@login_required
def delete_member(request, id):
member = get_object_or_404(Member, id=id)
member.delete()
return redirect('member_list')
@login_required
def book_loan_list(request):
book_loan = BookLoan.objects.all()
return render(request, 'book_loan_list.html', {'book_loan': book_loan})
@login_required
def book_loan_new(request):
members = Member.objects.all()
books = Book.objects.all()
if request.method == 'POST':
form = BookLoanForm(request.POST)
if form.is_valid():
form.save()
return redirect('book_loan_list')
else:
form = BookLoanForm()
return render(request, 'book_loan_new.html', {'form': form, 'members': members, 'books': books})
@login_required
def book_loan_update(request, id):
context = {}
book_loan = get_object_or_404(BookLoan, id=id)
form = BookLoanForm()
context['book_loan'] = book_loan
if request.method == 'POST':
form = BookLoanForm(request.POST, instance=book_loan)
if form.is_valid():
form.save()
return redirect('book_loan_list')
else:
form = BookLoanForm(instance=book_loan)
context['form'] = form
return render(request, 'book_loan_update.html', context)
@login_required
def book_loan_delete(request, id):
book_loan = get_object_or_404(BookLoan, id=id)
book_loan.delete()
return redirect('book_loan_list')
@login_required
def overdue_loans(request):
overdue_loans = BookLoan.objects.filter(due_date__lte=date.today())
over_due = overdue_loans.annotate(
dead=ExpressionWrapper(
F('due_date') - date.today(),
output_field=fields.DurationField()
)
).exclude(is_returned=True)
context = {
'over_due': over_due,
}
return render(request, 'overdue_loans.html', context)
@login_required
def near_outstanding_loans(request):
tomorow = date.today() + timedelta(days=1)
near_outstanding_loans = tomorow + timedelta(days=2)
near_date = BookLoan.objects.filter(due_date__gte=tomorow, due_date__lte=near_outstanding_loans)
near_outstanding_loans = near_date.annotate(
time_difference=ExpressionWrapper(
F('due_date') - date.today(),
output_field=fields.DurationField()
)
)
context = {'near_outstanding_loan': near_outstanding_loans}
return render(request, 'near_outstanding_loans.html', context)
@login_required
def librarian_list(request):
librarian = Librarian.objects.all()
return render(request, 'librarian_list.html', {'librarian': librarian})
@login_required
def librarian_new(request):
if request.method == 'POST':
user_form = userCreat(request.POST)
librarian_form = LibrarianForm(request.POST)
if user_form.is_valid() and librarian_form.is_valid():
user = user_form.save()
librarian = librarian_form.save(commit=False)
librarian.user = user
librarian.save()
return redirect('librarian_list')
else:
user_form = UserCreationForm()
librarian_form = LibrarianForm()
context = {'user_form': user_form, 'librarian_form': librarian_form}
return render(request, 'librarian_new.html', context)
# @login_required
# def librarian_update(request, pk):
# context = {}
# librarian = Librarian.objects.get(pk=pk)
# context['librarian'] = librarian
# if request.method == 'POST':
# form = LibrarianForm(request.POST, instance=librarian)
# if form.is_valid():
# form.save()
# return redirect('librarian_list')
# else:
# form = LibrarianForm(instance=librarian)
# context['form'] = form
# return render(request, 'librarian_update.html', context)
def librarian_update(request, pk):
librarian = get_object_or_404(librarian, pk=pk)
librarian_form = LibrarianUpdateForm(instance=librarian)
if request.method == 'POST':
user_form = LibrarianUpdateForm(request.POST, instance=librarian.user)
librarian_form = LibrarianUpdateForm(request.POST, instance=librarian)
if user_form.is_valid() and librarian_form.is_valid():
user_form.save()
librarian_form.save()
return redirect('librarian_list')
else:
user_form = LibrarianUpdateForm(instance=librarian.user)
context = {'user_form': user_form, 'librarian_form': librarian_form, 'librarian': librarian}
return render(request, 'librarian_update.html', context)
@login_required
def librarian_delete(request, pk):
librarian = Librarian.objects.get(pk=pk)
librarian.user.delete()
librarian.delete()
return redirect('librarian_list')
@login_required
def librarian_login_history(request):
login_history = LoginHistory.objects.all()
return render(request, 'librarian_login_history.html', {'login_history': login_history})
class BookList(ListView):
model = Book
template_name = "book_list.html"
context_object_name = 'books'
class BookCreateView(CreateView):
model = Book
form_class = BookForm
template_name = 'book_new.html'
success_url = reverse_lazy('book_list') # Adjust the success URL as needed
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
class CategoryListView(ListView):
model = Category
template_name = 'category_list.html'
context_object_name = 'categories'
\ No newline at end of file
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoproj.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment