Commit 7e4a69d3 authored by Fahmi's avatar Fahmi

serializer update

parent 6fe4d040
# permissions.py
from rest_framework import permissions
class MemberReadOnlyPermission(permissions.BasePermission):
message = "Anda tidak memiliki izin untuk melakukan operasi ini."
def has_permission(self, request, view):
# Hanya izinkan metode GET (read) untuk pengguna dengan peran 'member'
if request.user.is_member and request.method in permissions.SAFE_METHODS:
return True
return False
class LibrarianPermission(permissions.BasePermission):
message = "Anda tidak memiliki izin untuk melakukan operasi ini."
def has_permission(self, request, view):
# Pastikan pengguna terotentikasi sebelum mengakses atribut is_librarian
if request.user.is_authenticated:
return request.user.is_librarian
return False
\ No newline at end of file
......@@ -3,6 +3,8 @@ from .models import *
from rest_framework import serializers
from django.contrib.auth import authenticate, get_user_model
from datetime import date
from django.conf import settings
class UserLoginSerializer(serializers.Serializer):
username = serializers.CharField()
......@@ -74,9 +76,11 @@ class UserProfileSerializer(serializers.ModelSerializer):
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
fields = ['name']
class BookSerializer(serializers.ModelSerializer):
category = CategorySerializer()
class Meta:
model = Book
fields = '__all__'
......@@ -94,23 +98,57 @@ class LibrarianSerializer(serializers.ModelSerializer):
model = Librarian
fields = '__all__'
from rest_framework import serializers
class BookLoanSerializer(serializers.ModelSerializer):
book_image_url = serializers.SerializerMethodField()
book_title = serializers.SerializerMethodField()
member_name = serializers.SerializerMethodField()
loan_date = serializers.DateField(format='%Y-%m-%d', read_only=True)
due_date = serializers.DateField(format='%Y-%m-%d', read_only=True)
return_date = serializers.DateField(format='%Y-%m-%d', read_only=True)
class Meta:
model = BookLoan
fields = '__all__'
fields = ['book_image_url', 'book_title', 'member_name', 'loan_date', 'due_date', 'return_date', 'is_returned']
def get_book_image_url(self, obj):
if obj.book.image:
request = self.context.get('request')
return request.build_absolute_uri(obj.book.image.url)
return None
def get_book_title(self, obj):
return obj.book.title
def get_member_name(self, obj):
return obj.member.name
class OverdueLoanSerializer(serializers.ModelSerializer):
days_over = serializers.SerializerMethodField()
book_title = serializers.CharField(source='book.title')
book_image_url = serializers.SerializerMethodField()
member_name = serializers.CharField(source='member.name')
class Meta:
model = BookLoan
fields = '__all__'
def get_book_image_url(self, obj):
if obj.book.image:
request = self.context.get('request')
return request.build_absolute_uri(obj.book.image.url)
return None
def get_days_over(self, obj):
return (date.today() - obj.due_date).days
class NearOutstandingLoanSerializer(serializers.ModelSerializer):
days_left = serializers.SerializerMethodField()
book_title = serializers.CharField(source='book.title') # Tambahkan informasi judul buku
book_image_url = serializers.SerializerMethodField()
member_name = serializers.CharField(source='member.name')
class Meta:
model = BookLoan
......@@ -118,3 +156,45 @@ class NearOutstandingLoanSerializer(serializers.ModelSerializer):
def get_days_left(self, obj):
return (obj.due_date - date.today()).days
def get_book_image_url(self, obj):
if obj.book.image:
request = self.context.get('request')
return request.build_absolute_uri(obj.book.image.url)
return None
class MemberBookLoanSerializer(serializers.ModelSerializer):
class Meta:
model = BookLoan
fields = ['book','due_date']
class MemberBookLoanByIdSerializer(serializers.ModelSerializer):
class Meta:
model = BookLoan
fields = ['due_date']
class BookMemberSerializer(serializers.ModelSerializer):
image = serializers.SerializerMethodField('get_book_image_url')
class Meta:
model = Book
fields = ['title', 'image']
def get_book_image_url(self, obj):
if obj.image:
return self.context['request'].build_absolute_uri(obj.image.url)
return None
class BookLoanMemberSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
request = self.context.get('request')
book_serializer = BookMemberSerializer(instance.book, context={'request': request})
return {
'book_info': book_serializer.data,
'due_date': instance.due_date,
'is_returned': instance.is_returned
}
class Meta:
model = BookLoan
fields = ['book_info', 'due_date', 'is_returned']
\ No newline at end of file
......@@ -2,18 +2,57 @@
from django.urls import include, path
from api import views
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework.authtoken.views import obtain_auth_token
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
urlpatterns = [
# path('login/', obtain_auth_token, name='login'),
path('register-member/', views.MemberRegistrationAPIView.as_view(), name='api_register_member'),
path('register-librarian/', views.LibrarianRegistrationAPIView.as_view(), name='api_register_librarian'),
path('category/', views.CategoryList.as_view()),
path('category/<int:pk>/', views.CategoryDetail.as_view()),
path('book/', views.BookList.as_view()),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
path('book/', views.BookListNonAuth.as_view()),
path('auth/book/', views.BookList.as_view()),
path('book/search/', views.BookSearchView.as_view(), name='book-search-api'),
path('book/by-year/<int:year>/', views.BookListByYear.as_view(), name='book-list-by-year'),
path('book/by-category/<str:category>/', views.BookListByCategory.as_view(), name='book-list-by-category'),
path('book/by-custom/<int:year>/<str:category>/', views.BookListByYearAndCategory.as_view(), name='book-list-custom'),
path('book/<int:pk>/', views.BookDetail.as_view()),
path('member/', views.MemberList.as_view()),
path('member-login/', views.MemberLoginView.as_view(), name='member-login'),
path('member-logout/', views.MemberLogoutView.as_view(), name='member-logout-api'),
path('member/<int:pk>/', views.MemberDetail.as_view()),
path('librarian/', views.LibrarianList.as_view()),
path('librarian-login/', views.LibrarianLoginView.as_view(), name='librarian-login'),
path('librarian-logout/', views.LibrarianLogoutView.as_view(), name='member-logout-api'),
path('librarian/<int:pk>/', views.LibrarianDetail.as_view()),
path('bookloan/', views.BookLoanList.as_view()),
path('bookloan/<int:pk>/', views.BookLoanDetail.as_view()),
path('member/book-loan/', views.LoanSelectedBook.as_view()),
path('member/list-book-loan/', views.BookLoanViewSet.as_view({'get': 'list'})),
path('member/book-loan/<int:id>/', views.LoanSelectedBookById.as_view()),
path('near-outstanding-books/', views.NearOutstandingLoansAPIView.as_view(), name='near-outstanding-books-api'),
path('overdue-books/', views.OverdueLoansAPIView.as_view(), name='overdue-books-api'),
path('change-password/', views.ChangePasswordView.as_view(), name='change-password-api'),
path('change-profile/', views.ChangeProfileView.as_view(), name='change-profile-api'),
]
......
......@@ -3,6 +3,7 @@ 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 import viewsets
from datetime import date, timedelta
from rest_framework.decorators import api_view
from rest_framework.response import Response
......@@ -19,11 +20,15 @@ from rest_framework.authtoken.models import Token
from .permissions import *
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate, login, get_user_model
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
#set Pagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
page_query_param = 'page'
#regist librarian
class LibrarianRegistrationAPIView(generics.CreateAPIView):
......@@ -140,7 +145,7 @@ class ChangeProfileView(generics.UpdateAPIView):
#Category Create dan List
class CategoryList(generics.ListCreateAPIView):
permission_classes = [LibrarianPermission]
permission_classes = [IsAuthenticated]
queryset = Category.objects.all()
serializer_class = CategorySerializer
......@@ -152,12 +157,18 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Category.objects.all()
serializer_class = CategorySerializer
class BookListNonAuth(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
#Book Create dan List
class BookList(generics.ListCreateAPIView):
permission_classes = [MemberReadOnlyPermission|LibrarianPermission]
# permission_classes = [MemberReadOnlyPermission|LibrarianPermission]
permission_classes = [IsAuthenticated]
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = MyPageNumberPagination
#Book Update, Detail, Delete
class BookDetail(generics.RetrieveUpdateDestroyAPIView):
......@@ -196,15 +207,31 @@ class LibrarianDetail(generics.RetrieveUpdateDestroyAPIView):
#BookLoan Create dan List
class BookLoanList(generics.ListCreateAPIView):
permission_classes = [LibrarianPermission]
permission_classes = [IsAuthenticated, LibrarianPermission]
queryset = BookLoan.objects.all()
queryset = BookLoan.objects.all().select_related('book', 'member') # Include related objects
serializer_class = BookLoanSerializer
pagination_class = MyPageNumberPagination
# def list(self, request, *args, **kwargs):
# book_loans = self.get_queryset()
# serializer = self.get_serializer(book_loans, many=True)
# # Memuat objek buku dan anggota terkait
# data = []
# for loan in serializer.data:
# book = Book.objects.get(id=loan['book'])
# member = Member.objects.get(id=loan['member'])
# loan['book_title'] = book.title
# loan['member_name'] = member.name
# data.append(loan)
# return Response(data)
#BookLoan Update, Detail, Delete
class BookLoanDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [LibrarianPermission]
permission_classes = [IsAuthenticated, LibrarianPermission]
queryset = BookLoan.objects.all()
serializer_class = BookLoanSerializer
......@@ -215,8 +242,8 @@ class BookSearchView(generics.ListAPIView):
serializer_class = BookSerializer
def get_queryset(self):
book_name = self.request.query_params.get('book_name', '')
return Book.objects.filter(title__icontains=book_name)
title = self.request.query_params.get('title', '')
return Book.objects.filter(title__icontains=title)
#Book list By Year
class BookListByYear(generics.ListAPIView):
......@@ -241,7 +268,7 @@ class BookListByYearAndCategory(generics.ListAPIView):
#Book list By Category
class BookListByCategory(generics.ListAPIView):
permission_classes = [MemberReadOnlyPermission|LibrarianPermission]
permission_classes = [IsAuthenticated]
serializer_class = BookSerializer
......@@ -265,7 +292,7 @@ class NearOutstandingLoansAPIView(APIView):
)
)
serializer = NearOutstandingLoanSerializer(near_outstanding_loans, many=True)
serializer = NearOutstandingLoanSerializer(near_outstanding_loans, many=True, context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
#overdue loan list
......@@ -285,5 +312,60 @@ class OverdueLoansAPIView(APIView):
for loan in over_due:
loan.dead = abs(loan.dead.days)
serializer = OverdueLoanSerializer(over_due, many=True)
serializer = OverdueLoanSerializer(over_due, many=True, context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
# select bookloan
class LoanSelectedBook(APIView):
permission_classes = [IsAuthenticated]
serializer_class = MemberBookLoanSerializer
def post(self, request):
member = request.user.member
# Validasi data dari permintaan menggunakan serializer
serializer = MemberBookLoanSerializer(data=request.data)
if serializer.is_valid():
# Setel data yang diperlukan pada objek BookLoan
serializer.save( member=member)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# select bookloan by id
class LoanSelectedBookById(APIView):
permission_classes = [IsAuthenticated]
serializer_class = MemberBookLoanByIdSerializer
def post(self, request, id):
# Ambil objek buku berdasarkan book_id
book = get_object_or_404(Book, id=id)
member = request.user.member
# Periksa apakah buku sudah dipinjam
if BookLoan.objects.filter(book=book, member=member, is_returned=False).exists():
return Response({"message": "Buku sudah dipinjam."}, status=status.HTTP_400_BAD_REQUEST)
# Validasi data dari permintaan menggunakan serializer
serializer = MemberBookLoanByIdSerializer(data=request.data)
if serializer.is_valid():
# Setel data yang diperlukan pada objek BookLoan
serializer.save(book=book, member=member)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class BookLoanViewSet(viewsets.ViewSet):
permission_classes = [IsAuthenticated]
def list(self, request):
# Ambil semua objek BookLoan yang terkait dengan user (member) yang sedang login
book_loans = BookLoan.objects.filter(member=request.user.member)
# Serialize data BookLoan
serializer = BookLoanMemberSerializer(book_loans, many=True, context={'request': request})
# Kembalikan data BookLoan sebagai respons
return Response(serializer.data)
\ No newline at end of file
[{"model": "admin.logentry", "pk": 1, "fields": {"action_time": "2024-01-03T09:28:19.239Z", "user": 5, "content_type": 11, "object_id": "1", "object_repr": "Galang", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 2, "fields": {"action_time": "2024-01-03T10:09:58.034Z", "user": 5, "content_type": 9, "object_id": "1", "object_repr": "nunu", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 3, "fields": {"action_time": "2024-01-03T10:24:22.722Z", "user": 5, "content_type": 9, "object_id": "2", "object_repr": "Jumu", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 4, "fields": {"action_time": "2024-01-03T10:25:11.171Z", "user": 5, "content_type": 11, "object_id": "2", "object_repr": "admin", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 5, "fields": {"action_time": "2024-01-04T06:25:52.482Z", "user": 5, "content_type": 11, "object_id": "3", "object_repr": "Django", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 6, "fields": {"action_time": "2024-01-04T06:27:51.111Z", "user": 5, "content_type": 9, "object_id": "3", "object_repr": "Primus", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 7, "fields": {"action_time": "2024-01-04T09:03:26.799Z", "user": 5, "content_type": 6, "object_id": "5", "object_repr": "admin", "action_flag": 2, "change_message": "[{\"changed\": {\"fields\": [\"Email address\"]}}]"}}, {"model": "admin.logentry", "pk": 8, "fields": {"action_time": "2024-01-04T09:31:21.527Z", "user": 5, "content_type": 9, "object_id": "4", "object_repr": "devdev", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 9, "fields": {"action_time": "2024-01-05T02:06:26.558Z", "user": 5, "content_type": 9, "object_id": "5", "object_repr": "Bagasmin", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 10, "fields": {"action_time": "2024-01-05T04:17:39.881Z", "user": 5, "content_type": 6, "object_id": "2", "object_repr": "galangrambu12", "action_flag": 2, "change_message": "[{\"changed\": {\"fields\": [\"Groups\", \"Email address\"]}}]"}}, {"model": "admin.logentry", "pk": 11, "fields": {"action_time": "2024-01-05T07:10:28.542Z", "user": 5, "content_type": 11, "object_id": "4", "object_repr": "Fahmi", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 12, "fields": {"action_time": "2024-01-05T07:17:22.211Z", "user": 5, "content_type": 11, "object_id": "5", "object_repr": "Ninja", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 13, "fields": {"action_time": "2024-01-05T07:18:48.634Z", "user": 5, "content_type": 11, "object_id": "6", "object_repr": "Senopati", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 14, "fields": {"action_time": "2024-01-05T07:19:20.726Z", "user": 5, "content_type": 11, "object_id": "6", "object_repr": "Adminas", "action_flag": 2, "change_message": "[{\"changed\": {\"fields\": [\"Name\"]}}]"}}, {"model": "admin.logentry", "pk": 15, "fields": {"action_time": "2024-01-05T07:20:40.111Z", "user": 5, "content_type": 11, "object_id": "7", "object_repr": "Saputra", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 16, "fields": {"action_time": "2024-01-05T07:26:16.360Z", "user": 5, "content_type": 9, "object_id": "6", "object_repr": "Elyas", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 17, "fields": {"action_time": "2024-01-09T03:58:40.120Z", "user": 5, "content_type": 11, "object_id": "8", "object_repr": "Shuna", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 18, "fields": {"action_time": "2024-01-12T03:35:30.933Z", "user": 5, "content_type": 9, "object_id": "7", "object_repr": "member78", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add log entry", "content_type": 1, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change log entry", "content_type": 1, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete log entry", "content_type": 1, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can view log entry", "content_type": 1, "codename": "view_logentry"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can view permission", "content_type": 2, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can view group", "content_type": 3, "codename": "view_group"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add content type", "content_type": 4, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change content type", "content_type": 4, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete content type", "content_type": 4, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can view content type", "content_type": 4, "codename": "view_contenttype"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can add session", "content_type": 5, "codename": "add_session"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can change session", "content_type": 5, "codename": "change_session"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can delete session", "content_type": 5, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can view session", "content_type": 5, "codename": "view_session"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can add user", "content_type": 6, "codename": "add_customuser"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can change user", "content_type": 6, "codename": "change_customuser"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can delete user", "content_type": 6, "codename": "delete_customuser"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can view user", "content_type": 6, "codename": "view_customuser"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add book", "content_type": 7, "codename": "add_book"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change book", "content_type": 7, "codename": "change_book"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete book", "content_type": 7, "codename": "delete_book"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can view book", "content_type": 7, "codename": "view_book"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can add category", "content_type": 8, "codename": "add_category"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can change category", "content_type": 8, "codename": "change_category"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can delete category", "content_type": 8, "codename": "delete_category"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can view category", "content_type": 8, "codename": "view_category"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can add member", "content_type": 9, "codename": "add_member"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can change member", "content_type": 9, "codename": "change_member"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can delete member", "content_type": 9, "codename": "delete_member"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can view member", "content_type": 9, "codename": "view_member"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add login history", "content_type": 10, "codename": "add_loginhistory"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change login history", "content_type": 10, "codename": "change_loginhistory"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete login history", "content_type": 10, "codename": "delete_loginhistory"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can view login history", "content_type": 10, "codename": "view_loginhistory"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can add librarian", "content_type": 11, "codename": "add_librarian"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can change librarian", "content_type": 11, "codename": "change_librarian"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can delete librarian", "content_type": 11, "codename": "delete_librarian"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can view librarian", "content_type": 11, "codename": "view_librarian"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can add book loan", "content_type": 12, "codename": "add_bookloan"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can change book loan", "content_type": 12, "codename": "change_bookloan"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can delete book loan", "content_type": 12, "codename": "delete_bookloan"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can view book loan", "content_type": 12, "codename": "view_bookloan"}}, {"model": "auth.permission", "pk": 49, "fields": {"name": "Can add member permission", "content_type": 13, "codename": "add_memberpermission"}}, {"model": "auth.permission", "pk": 50, "fields": {"name": "Can change member permission", "content_type": 13, "codename": "change_memberpermission"}}, {"model": "auth.permission", "pk": 51, "fields": {"name": "Can delete member permission", "content_type": 13, "codename": "delete_memberpermission"}}, {"model": "auth.permission", "pk": 52, "fields": {"name": "Can view member permission", "content_type": 13, "codename": "view_memberpermission"}}, {"model": "auth.permission", "pk": 53, "fields": {"name": "Can view buku", "content_type": 13, "codename": "view_buku"}}, {"model": "auth.permission", "pk": 54, "fields": {"name": "Can add Token", "content_type": 14, "codename": "add_token"}}, {"model": "auth.permission", "pk": 55, "fields": {"name": "Can change Token", "content_type": 14, "codename": "change_token"}}, {"model": "auth.permission", "pk": 56, "fields": {"name": "Can delete Token", "content_type": 14, "codename": "delete_token"}}, {"model": "auth.permission", "pk": 57, "fields": {"name": "Can view Token", "content_type": 14, "codename": "view_token"}}, {"model": "auth.permission", "pk": 58, "fields": {"name": "Can add token", "content_type": 15, "codename": "add_tokenproxy"}}, {"model": "auth.permission", "pk": 59, "fields": {"name": "Can change token", "content_type": 15, "codename": "change_tokenproxy"}}, {"model": "auth.permission", "pk": 60, "fields": {"name": "Can delete token", "content_type": 15, "codename": "delete_tokenproxy"}}, {"model": "auth.permission", "pk": 61, "fields": {"name": "Can view token", "content_type": 15, "codename": "view_tokenproxy"}}, {"model": "auth.permission", "pk": 62, "fields": {"name": "Can add blacklisted token", "content_type": 16, "codename": "add_blacklistedtoken"}}, {"model": "auth.permission", "pk": 63, "fields": {"name": "Can change blacklisted token", "content_type": 16, "codename": "change_blacklistedtoken"}}, {"model": "auth.permission", "pk": 64, "fields": {"name": "Can delete blacklisted token", "content_type": 16, "codename": "delete_blacklistedtoken"}}, {"model": "auth.permission", "pk": 65, "fields": {"name": "Can view blacklisted token", "content_type": 16, "codename": "view_blacklistedtoken"}}, {"model": "auth.permission", "pk": 66, "fields": {"name": "Can add outstanding token", "content_type": 17, "codename": "add_outstandingtoken"}}, {"model": "auth.permission", "pk": 67, "fields": {"name": "Can change outstanding token", "content_type": 17, "codename": "change_outstandingtoken"}}, {"model": "auth.permission", "pk": 68, "fields": {"name": "Can delete outstanding token", "content_type": 17, "codename": "delete_outstandingtoken"}}, {"model": "auth.permission", "pk": 69, "fields": {"name": "Can view outstanding token", "content_type": 17, "codename": "view_outstandingtoken"}}, {"model": "auth.group", "pk": 1, "fields": {"name": "Librarian", "permissions": []}}, {"model": "auth.group", "pk": 2, "fields": {"name": "Pustakawan", "permissions": []}}, {"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "library", "model": "customuser"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "library", "model": "book"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "library", "model": "category"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "library", "model": "member"}}, {"model": "contenttypes.contenttype", "pk": 10, "fields": {"app_label": "library", "model": "loginhistory"}}, {"model": "contenttypes.contenttype", "pk": 11, "fields": {"app_label": "library", "model": "librarian"}}, {"model": "contenttypes.contenttype", "pk": 12, "fields": {"app_label": "library", "model": "bookloan"}}, {"model": "contenttypes.contenttype", "pk": 13, "fields": {"app_label": "library", "model": "memberpermission"}}, {"model": "contenttypes.contenttype", "pk": 14, "fields": {"app_label": "authtoken", "model": "token"}}, {"model": "contenttypes.contenttype", "pk": 15, "fields": {"app_label": "authtoken", "model": "tokenproxy"}}, {"model": "contenttypes.contenttype", "pk": 16, "fields": {"app_label": "token_blacklist", "model": "blacklistedtoken"}}, {"model": "contenttypes.contenttype", "pk": 17, "fields": {"app_label": "token_blacklist", "model": "outstandingtoken"}}, {"model": "sessions.session", "pk": "0ok5cf23fih7h0g2ohfcmtjqrnb5srfi", "fields": {"session_data": ".eJxVjEEOwiAQRe_C2hBwWmBcuvcMZGAGqZo2Ke3KeHfbpAvdvvf-f6tI61Lj2mSOA6uL6tXplyXKTxl3wQ8a75PO07jMQ9J7og_b9G1ieV2P9u-gUqvbmhAseAghkQXpOEku4NiZkgwykrDfIIARhOxK8eBsjw7NOXQSANXnC_B3N70:1rOBgV:QqDPiIgfx8zZ9-PR2t59iCrqf9-DTtTmDuGNxzHAf6U", "expire_date": "2024-01-26T07:10:31.588Z"}}, {"model": "sessions.session", "pk": "89xoudzeej3jyuronhmctstuby1sc0oc", "fields": {"session_data": ".eJxVjEEOgjAQRe_StWk6hU7BpXvO0EyZqaCmTSisjHcXEha6_e-9_1aBtnUKW5UlzKyuChp1-R0jjU_JB-EH5XvRY8nrMkd9KPqkVQ-F5XU73b-Dieq012Q7B0LU9rYF7iL2CEgWhZwnBgDj0QlDHxOalGwiQd_A7jEYAqs-X_qMN8E:1rLJzj:bcGY6Uf3SGfgsnKg07I4y-0EfFbcoYehiDOABS00Sy8", "expire_date": "2024-01-18T09:26:31.230Z"}}, {"model": "sessions.session", "pk": "ca0wmawk8d2keobswcl364c8kp6ik6n6", "fields": {"session_data": "e30:1rKxKi:lkUkbwQZMWzYpywW4RHvU-v5ILjuoNNT69H7LSEiZLs", "expire_date": "2024-01-17T09:14:40.001Z"}}, {"model": "sessions.session", "pk": "kl0vpczf4pxy6j4by01fut3lshyy9hlz", "fields": {"session_data": "e30:1rKwba:Vg3obgbwLCVpt2D4eJBMQNhvcksmn8mMhWKOhCwPsWE", "expire_date": "2024-01-17T08:28:02.974Z"}}, {"model": "library.customuser", "pk": 1, "fields": {"password": "pbkdf2_sha256$600000$9hSplZ32xa6VVQXJQ41qLX$lZ91MCIgqBlUM0Ar9mJairfd1HQ8aomrFnh5/x+6r4c=", "last_login": "2024-01-05T07:10:41.245Z", "is_superuser": false, "username": "admin123", "first_name": "admin", "last_name": "Utama", "email": "admin123@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T03:59:10.504Z", "is_member": false, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 2, "fields": {"password": "pbkdf2_sha256$600000$68gAP9fbHVa8VWrVvyW2i3$4GVir6lgb1ehP/A7blcSwDQfDjIivrSdLs00exhi14Y=", "last_login": "2024-01-03T09:13:21Z", "is_superuser": false, "username": "galangrambu12", "first_name": "Galang", "last_name": "Rambu", "email": "galang@dev.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T08:10:29Z", "is_member": false, "is_librarian": true, "groups": [1], "user_permissions": []}}, {"model": "library.customuser", "pk": 3, "fields": {"password": "pbkdf2_sha256$600000$y1jEnPADcWHaB7HLF6RHp1$+18eqnLDe4ur/kcGxWDP99Ue1EMe6FoaySCXx2JB7e0=", "last_login": "2024-01-03T08:29:02.805Z", "is_superuser": false, "username": "dmspatan", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T08:28:02.715Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 4, "fields": {"password": "pbkdf2_sha256$600000$iHpI913cXtBgGRHF7OwJIJ$B3EnzbCB3uH0sR0YPZ1weEaqycOdwkm5N+pLkwp+AvE=", "last_login": "2024-01-03T09:15:22.792Z", "is_superuser": false, "username": "adminja123", "first_name": "ninja", "last_name": "Admin", "email": "adminja123@dev.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T09:14:39.483Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 5, "fields": {"password": "pbkdf2_sha256$600000$jAe4pUGNpXFDzJSBoMIVqP$RhgDrnKpS3Eei5F2QWwb6kdYM3k70zq0aYzWgyr9lZY=", "last_login": "2024-01-12T07:10:31.585Z", "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "admin@dev.com", "is_staff": true, "is_active": true, "date_joined": "2024-01-03T09:22:20Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 6, "fields": {"password": "pbkdf2_sha256$600000$JaEHJOXkCkk4CGwftPVvYy$V0SBP/vvXr8MJi6KpLtG1iabnOadwH6HPtaTVGEOWeE=", "last_login": "2024-01-04T10:59:10.325Z", "is_superuser": false, "username": "nunura", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T10:06:27.904Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 7, "fields": {"password": "pbkdf2_sha256$600000$ENweAvHSIuCq7RNzBfGslP$ecx9VzmY8Ey9fWyre4+F9NPsK6HbFvyqV8YOssD7Kcc=", "last_login": "2024-01-03T10:22:53.822Z", "is_superuser": false, "username": "jumuan", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-03T10:22:53.566Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 8, "fields": {"password": "pbkdf2_sha256$600000$PSTxg6GGjDSOtmmQ27OFN0$rIaE306k9Wk1A6K/QM34IzFcynO4/s1oGkRuy/EfAGs=", "last_login": "2024-01-04T05:49:27.434Z", "is_superuser": false, "username": "slardar", "first_name": "Sala Dara", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T05:49:26.855Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 9, "fields": {"password": "pbkdf2_sha256$600000$6W9KobdDKO4TMSC6jZYgAr$F118sOK5Z5MHbYe8Tk3K2wBnNHSrr81GWQmYLZpJjgo=", "last_login": "2024-01-04T05:50:38.215Z", "is_superuser": false, "username": "mutmut", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T05:50:37.897Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 10, "fields": {"password": "pbkdf2_sha256$600000$0Q3xx75M6i8QqLRrNZgsae$e17vb+H5PCDCVs5QknbOR88dzEHNbabfAVdIYrEcIq4=", "last_login": "2024-01-04T05:52:21.955Z", "is_superuser": false, "username": "juggernaut", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T05:52:21.698Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 11, "fields": {"password": "gagal1234", "last_login": "2024-01-04T06:21:58.548Z", "is_superuser": false, "username": "django", "first_name": "", "last_name": "", "email": "django@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T06:21:58.540Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 12, "fields": {"password": "siprimus12", "last_login": "2024-01-04T06:22:53.378Z", "is_superuser": false, "username": "primus22", "first_name": "", "last_name": "", "email": "priprimus@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T06:22:53.370Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 13, "fields": {"password": "xamu3456", "last_login": "2024-01-04T09:26:31.228Z", "is_superuser": false, "username": "devadm", "first_name": "", "last_name": "", "email": "admdev@dev.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T09:26:31.180Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 14, "fields": {"password": "pbkdf2_sha256$600000$HQnLMPcE7GFkqX4QOymMjl$ahvTSHRHl8Lk2a5t/SdK7rJXGs15EY6bSsJaMNgQbxs=", "last_login": "2024-01-09T08:48:30.830Z", "is_superuser": false, "username": "admin12", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T09:42:48.184Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 15, "fields": {"password": "pbkdf2_sha256$600000$bRBzWwIBVigdjrhU166Zpz$YqxhuK8jhYAL0V1TPR1fROfAggMEe8SPUD4Nv7TK+rQ=", "last_login": null, "is_superuser": false, "username": "opaksing", "first_name": "", "last_name": "", "email": "opak@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T10:03:32.193Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 16, "fields": {"password": "pbkdf2_sha256$600000$w3oGsRg1jPWCXU3hxi6xG9$DjCysL6IbwEYnVh9dMKZUyJDXZWc6PfqVMzQEzx8jrE=", "last_login": "2024-01-04T10:53:28.052Z", "is_superuser": false, "username": "gabusbaru", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T10:53:27.794Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 17, "fields": {"password": "pbkdf2_sha256$600000$i62IV0QTcRIQxTHtWI8F06$W4hOSnPEnGkBA0wFwytAigGOZkDyX+rqtU9/dGYH9Lc=", "last_login": "2024-01-04T10:54:39.706Z", "is_superuser": false, "username": "admin777", "first_name": "Adminas", "last_name": "", "email": "admin777@min.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-04T10:54:39.163Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 18, "fields": {"password": "pbkdf2_sha256$600000$ggqcYXT5JrV6I9CVuZHCSE$tkDO6g4Y7eitywu+VWzoZajhmhfyNh+5DUwRKwfWoF8=", "last_login": "2024-01-05T07:06:50.078Z", "is_superuser": false, "username": "adminbaru", "first_name": "Saputra", "last_name": "", "email": "admin11@dev.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T07:04:39.181Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 19, "fields": {"password": "pbkdf2_sha256$600000$52YkeMrIgEOqfNT0kCRHSy$9tqtxr1Arz6V9bS+ff3qn8YHeVB7gpCxK62tM1d2hSY=", "last_login": "2024-01-05T07:26:35.427Z", "is_superuser": false, "username": "ecigraf", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T07:24:33.995Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 20, "fields": {"password": "pbkdf2_sha256$600000$TiItBPrMqPo6v5fxC7kwVG$ZjTsJSYX+evMgyTDnYs4ye5FVWlPZmLOAxSZu4Vyacw=", "last_login": "2024-01-05T08:50:41.987Z", "is_superuser": false, "username": "librarian1", "first_name": "", "last_name": "", "email": "libradong@dev.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T08:50:41.476Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 21, "fields": {"password": "pbkdf2_sha256$600000$F96jsWLiXHAIWN0RFBa3jc$HIqBrGYGSYUpy0/jq3Z8g7DleqiLeWvefkrtuJL0NpQ=", "last_login": null, "is_superuser": false, "username": "rofi123", "first_name": "", "last_name": "", "email": "rofi@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T09:02:34.409Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 22, "fields": {"password": "pbkdf2_sha256$600000$Ogf04U4I5WUTYF6Eo9c7i1$PVWjcV+lZB/ZC032sPcIYlOPCu5tE9nSKStF40HRBSw=", "last_login": null, "is_superuser": false, "username": "ravintola123123", "first_name": "", "last_name": "", "email": "ravin@gmail.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T09:12:43.600Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 23, "fields": {"password": "pbkdf2_sha256$600000$gFhVQ0E6ynaqlLstFzJbNH$3Tkn2c3bGrN9eJWf5/QP9ASlQNbYZK9x4u0qu/ocJdI=", "last_login": "2024-01-05T09:32:21.149Z", "is_superuser": false, "username": "memberbaru1", "first_name": "", "last_name": "", "email": "barumember@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T09:24:56.630Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 24, "fields": {"password": "pbkdf2_sha256$600000$X5ZXSTGJ0hYx2n7uyUOJtp$1honLGaHRodGG454zShqBuybAOEQ3JtGIda5/u8SCtU=", "last_login": "2024-01-05T09:27:13.336Z", "is_superuser": false, "username": "librarianbaru12", "first_name": "", "last_name": "Langga", "email": "pustaka@libra.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T09:27:09.497Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 25, "fields": {"password": "pbkdf2_sha256$600000$Ze6lUoJc70bfa0luS7nzTJ$I+hfttVgLH5w48dCAdVRlmTYg0ZI8DnpBmSRluPhwM0=", "last_login": null, "is_superuser": false, "username": "memberlagi1", "first_name": "", "last_name": "", "email": "memberlagi12@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T10:53:26.939Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 26, "fields": {"password": "pbkdf2_sha256$600000$hMLk2wC5VENiZYRFpfnsFD$prfLc/PpOaKMhubR50/StmKKSX6hUXYUJcDL34HOK/k=", "last_login": null, "is_superuser": false, "username": "asd21", "first_name": "", "last_name": "", "email": "asd@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T11:17:47.503Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 27, "fields": {"password": "pbkdf2_sha256$600000$uAT80E8kthqgJ0NogdVwPy$PEt73gkLmYlDoSzlnCxhtkNZdu0pyi/ItdGKbfl6AYI=", "last_login": null, "is_superuser": false, "username": "member77", "first_name": "", "last_name": "", "email": "member77@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-05T11:44:39.860Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 28, "fields": {"password": "pbkdf2_sha256$600000$Wfh0BwyyWQ2unizkF6rp9d$NXz/Mga6xqXaxUFq0/Ng2xw1WIo7WoUim5/k2X8qXwo=", "last_login": null, "is_superuser": false, "username": "member78", "first_name": "Gadis", "last_name": "Meldi", "email": "adisga@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-08T02:32:21.510Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 29, "fields": {"password": "pbkdf2_sha256$600000$36SoJguErMrN3nT92etzYv$koU5kDAWcFB/yWqmnwF4P/SrKnCovqm2eiW6tAHBQUI=", "last_login": "2024-01-10T07:05:01.555Z", "is_superuser": false, "username": "librarian778", "first_name": "Shuna", "last_name": "Leo", "email": "leoshuna@gmailc.om", "is_staff": false, "is_active": true, "date_joined": "2024-01-08T02:36:46.268Z", "is_member": false, "is_librarian": true, "groups": [], "user_permissions": []}}, {"model": "library.customuser", "pk": 30, "fields": {"password": "pbkdf2_sha256$600000$qvHS2osGtEW4NH8M0CbiO6$QdulcKJtRZfaCNkp5eI9mRgDPX+Uzgi5sU5PI27UJug=", "last_login": null, "is_superuser": false, "username": "member781", "first_name": "", "last_name": "", "email": "member781@member.com", "is_staff": false, "is_active": true, "date_joined": "2024-01-10T06:47:40.946Z", "is_member": true, "is_librarian": false, "groups": [], "user_permissions": []}}, {"model": "library.category", "pk": 1, "fields": {"name": "Horror"}}, {"model": "library.category", "pk": 2, "fields": {"name": "Misteri"}}, {"model": "library.category", "pk": 3, "fields": {"name": "Pendidikan"}}, {"model": "library.category", "pk": 4, "fields": {"name": "Anime"}}, {"model": "library.category", "pk": 5, "fields": {"name": "Novel"}}, {"model": "library.category", "pk": 6, "fields": {"name": "Light Novel"}}, {"model": "library.category", "pk": 7, "fields": {"name": "Sejarah"}}, {"model": "library.category", "pk": 8, "fields": {"name": "Biografi"}}, {"model": "library.book", "pk": 1, "fields": {"title": "Two Piece", "author": "Eichiro Oda", "publisher": "Shonen Jump", "category": 4, "date_publish": 1999, "image": "book_images/peakpx-c.jpg", "isbn": "10104560"}}, {"model": "library.book", "pk": 2, "fields": {"title": "Lawang Sewu", "author": "Ki Pranata", "publisher": "Dunia Malam", "category": 5, "date_publish": 2003, "image": "book_images/peakpx-c_KYzWbMV.jpg", "isbn": "10104851"}}, {"model": "library.book", "pk": 4, "fields": {"title": "Misteri Akhir Zaman", "author": "R Tolkien", "publisher": "Panorama Picture", "category": 2, "date_publish": 2003, "image": "book_images/Buku-Misteri-Akhir-Zaman-cover-2.jpg", "isbn": "112004515"}}, {"model": "library.book", "pk": 5, "fields": {"title": "hunter x hunter", "author": "Togashi", "publisher": "Shonen Jump", "category": 4, "date_publish": 2001, "image": "", "isbn": "12109561"}}, {"model": "library.book", "pk": 6, "fields": {"title": "Baru", "author": "Ravintola", "publisher": "Jga", "category": 1, "date_publish": 2010, "image": "book_images/perpustakaan.jpg", "isbn": "14578546"}}, {"model": "library.book", "pk": 7, "fields": {"title": "BJ Habiebie", "author": "Samsudin", "publisher": "Terang", "category": 8, "date_publish": 2003, "image": "book_images/perpustakaan_S2Z63WG.jpg", "isbn": "456186461"}}, {"model": "library.book", "pk": 8, "fields": {"title": "Japan Feodal", "author": "Robert G", "publisher": "Braith", "category": 7, "date_publish": 1997, "image": "book_images/perpustakaan_Aenge5t.jpg", "isbn": "784569221"}}, {"model": "library.member", "pk": 1, "fields": {"user": 6, "name": "nunu", "address": "kemiri jalan 3", "email": "navrus66@gmail.com", "birth_place": "jakarta", "date_birth": "1994-12-23", "phone_number": "+6281213566175"}}, {"model": "library.member", "pk": 2, "fields": {"user": 7, "name": "Jumu", "address": "Kali Malang", "email": "jumuan@gmail.com", "birth_place": "Bekasi", "date_birth": "1977-12-13", "phone_number": "+628124561234"}}, {"model": "library.member", "pk": 3, "fields": {"user": 12, "name": "Primus", "address": "Majapahit 11", "email": "priprimus@gmail.com", "birth_place": "Asgrad", "date_birth": "1982-03-26", "phone_number": "+6283812467548"}}, {"model": "library.member", "pk": 4, "fields": {"user": 13, "name": "devdev", "address": "devdev", "email": "admdev@dev.com", "birth_place": "Cianjur", "date_birth": "1975-12-12", "phone_number": "+6281246952365"}}, {"model": "library.member", "pk": 5, "fields": {"user": 14, "name": "rofi rahmat", "address": "Tanjung Duren Timur", "email": "admin12@gmail.com", "birth_place": "jakarta", "date_birth": "1985-10-23", "phone_number": "+628386595412"}}, {"model": "library.member", "pk": 6, "fields": {"user": 19, "name": "Elyas", "address": "Gili Trawangan, Lombok", "email": "ecigraf@member.com", "birth_place": "Bima", "date_birth": "2001-03-24", "phone_number": "+628114563298"}}, {"model": "library.member", "pk": 7, "fields": {"user": 28, "name": "member78", "address": "jakarta", "email": "member78@gmail.com", "birth_place": "Asgrad", "date_birth": "1977-12-19", "phone_number": "+6285466351152"}}, {"model": "library.bookloan", "pk": 1, "fields": {"book": 1, "member": 1, "loan_date": "2024-01-03", "due_date": "2024-01-03", "return_date": "2024-01-11", "is_returned": true}}, {"model": "library.bookloan", "pk": 2, "fields": {"book": 1, "member": 3, "loan_date": "2024-01-04", "due_date": "2024-01-05", "return_date": "2024-01-11", "is_returned": true}}, {"model": "library.bookloan", "pk": 3, "fields": {"book": 2, "member": 1, "loan_date": "2024-01-05", "due_date": "2024-01-07", "return_date": "2024-01-11", "is_returned": true}}, {"model": "library.bookloan", "pk": 5, "fields": {"book": 1, "member": 3, "loan_date": "2024-01-05", "due_date": "2024-01-07", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 6, "fields": {"book": 5, "member": 6, "loan_date": "2024-01-08", "due_date": "2024-01-10", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 7, "fields": {"book": 4, "member": 4, "loan_date": "2024-01-08", "due_date": "2024-01-11", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 8, "fields": {"book": 5, "member": 3, "loan_date": "2024-01-09", "due_date": "2024-01-12", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 9, "fields": {"book": 4, "member": 3, "loan_date": "2024-01-10", "due_date": "2024-01-14", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 10, "fields": {"book": 5, "member": 2, "loan_date": "2024-01-10", "due_date": "2024-01-13", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 11, "fields": {"book": 4, "member": 3, "loan_date": "2024-01-10", "due_date": "2024-01-13", "return_date": "2024-01-10", "is_returned": true}}, {"model": "library.bookloan", "pk": 12, "fields": {"book": 6, "member": 7, "loan_date": "2024-01-12", "due_date": "2024-01-14", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 17, "fields": {"book": 2, "member": 7, "loan_date": "2024-01-12", "due_date": "2024-01-17", "return_date": null, "is_returned": false}}, {"model": "library.bookloan", "pk": 18, "fields": {"book": 6, "member": 7, "loan_date": "2024-01-12", "due_date": "2024-01-18", "return_date": null, "is_returned": false}}, {"model": "library.librarian", "pk": 1, "fields": {"user": 2, "name": "Gilang", "address": "Medan Raya II", "last_name": "Ramadhan S", "birth_place": "Jakarta", "date_birth": "1985-12-10", "phone_number": "+6281245748891"}}, {"model": "library.librarian", "pk": 2, "fields": {"user": 5, "name": "admin", "address": "kantor", "last_name": "admin juga", "birth_place": "jakarta", "date_birth": "2000-05-23", "phone_number": "+628454787141"}}, {"model": "library.librarian", "pk": 3, "fields": {"user": 11, "name": "Django", "address": "manca 11", "last_name": "Frame", "birth_place": "Batu Raden", "date_birth": "1978-03-21", "phone_number": "083869857456"}}, {"model": "library.librarian", "pk": 4, "fields": {"user": 1, "name": "Zidane12", "address": "Tangerang", "last_name": "Kareem", "birth_place": "Jakarta", "date_birth": "1995-03-16", "phone_number": "+6285698456987"}}, {"model": "library.librarian", "pk": 5, "fields": {"user": 4, "name": "Ninja", "address": "Konoha", "last_name": "Uzumaki", "birth_place": "Tsunagakure", "date_birth": "1999-02-22", "phone_number": "+628214569824"}}, {"model": "library.librarian", "pk": 6, "fields": {"user": 17, "name": "Adminas", "address": "jalan 77 Kaliurang", "last_name": "Ringo", "birth_place": "Slema", "date_birth": "2000-06-30", "phone_number": "+62854963214"}}, {"model": "library.librarian", "pk": 7, "fields": {"user": 18, "name": "Saputra11", "address": "bandung", "last_name": "Guntur", "birth_place": "Bandung", "date_birth": "2024-01-05", "phone_number": "+6285698456987"}}, {"model": "library.librarian", "pk": 8, "fields": {"user": 29, "name": "Shuna", "address": "Jura Tempest Rempokoku", "last_name": "Leo", "birth_place": "Rimuru City", "date_birth": "1977-12-13", "phone_number": "+628154787745"}}, {"model": "library.loginhistory", "pk": 1, "fields": {"librarian": 1, "login_time": "2024-01-03T03:59:10.758Z"}}, {"model": "library.loginhistory", "pk": 2, "fields": {"librarian": 1, "login_time": "2024-01-03T06:25:55.056Z"}}, {"model": "library.loginhistory", "pk": 3, "fields": {"librarian": 1, "login_time": "2024-01-03T06:53:24.249Z"}}, {"model": "library.loginhistory", "pk": 4, "fields": {"librarian": 2, "login_time": "2024-01-03T08:21:03.323Z"}}, {"model": "library.loginhistory", "pk": 5, "fields": {"librarian": 2, "login_time": "2024-01-03T08:24:26.408Z"}}, {"model": "library.loginhistory", "pk": 6, "fields": {"librarian": 2, "login_time": "2024-01-03T08:24:58.149Z"}}, {"model": "library.loginhistory", "pk": 7, "fields": {"librarian": 2, "login_time": "2024-01-03T08:26:08.554Z"}}, {"model": "library.loginhistory", "pk": 8, "fields": {"librarian": 3, "login_time": "2024-01-03T08:28:02.976Z"}}, {"model": "library.loginhistory", "pk": 9, "fields": {"librarian": 3, "login_time": "2024-01-03T08:29:02.803Z"}}, {"model": "library.loginhistory", "pk": 10, "fields": {"librarian": 2, "login_time": "2024-01-03T09:13:21.434Z"}}, {"model": "library.loginhistory", "pk": 11, "fields": {"librarian": 4, "login_time": "2024-01-03T09:14:40.003Z"}}, {"model": "library.loginhistory", "pk": 12, "fields": {"librarian": 4, "login_time": "2024-01-03T09:15:22.790Z"}}, {"model": "library.loginhistory", "pk": 13, "fields": {"librarian": 5, "login_time": "2024-01-03T09:22:40.038Z"}}, {"model": "library.loginhistory", "pk": 14, "fields": {"librarian": 6, "login_time": "2024-01-03T10:06:28.229Z"}}, {"model": "library.loginhistory", "pk": 15, "fields": {"librarian": 5, "login_time": "2024-01-03T10:08:55.867Z"}}, {"model": "library.loginhistory", "pk": 16, "fields": {"librarian": 6, "login_time": "2024-01-03T10:11:56.842Z"}}, {"model": "library.loginhistory", "pk": 17, "fields": {"librarian": 6, "login_time": "2024-01-03T10:13:05.784Z"}}, {"model": "library.loginhistory", "pk": 18, "fields": {"librarian": 5, "login_time": "2024-01-03T10:14:53.472Z"}}, {"model": "library.loginhistory", "pk": 19, "fields": {"librarian": 7, "login_time": "2024-01-03T10:22:53.820Z"}}, {"model": "library.loginhistory", "pk": 20, "fields": {"librarian": 5, "login_time": "2024-01-03T10:23:15.198Z"}}, {"model": "library.loginhistory", "pk": 21, "fields": {"librarian": 5, "login_time": "2024-01-03T11:04:42.162Z"}}, {"model": "library.loginhistory", "pk": 22, "fields": {"librarian": 5, "login_time": "2024-01-03T11:07:25.465Z"}}, {"model": "library.loginhistory", "pk": 23, "fields": {"librarian": 5, "login_time": "2024-01-03T11:09:12.226Z"}}, {"model": "library.loginhistory", "pk": 24, "fields": {"librarian": 8, "login_time": "2024-01-04T05:49:27.432Z"}}, {"model": "library.loginhistory", "pk": 25, "fields": {"librarian": 9, "login_time": "2024-01-04T05:50:38.213Z"}}, {"model": "library.loginhistory", "pk": 26, "fields": {"librarian": 10, "login_time": "2024-01-04T05:52:21.953Z"}}, {"model": "library.loginhistory", "pk": 27, "fields": {"librarian": 11, "login_time": "2024-01-04T06:21:58.546Z"}}, {"model": "library.loginhistory", "pk": 28, "fields": {"librarian": 12, "login_time": "2024-01-04T06:22:53.376Z"}}, {"model": "library.loginhistory", "pk": 29, "fields": {"librarian": 5, "login_time": "2024-01-04T06:23:11.376Z"}}, {"model": "library.loginhistory", "pk": 30, "fields": {"librarian": 5, "login_time": "2024-01-04T08:58:45.907Z"}}, {"model": "library.loginhistory", "pk": 31, "fields": {"librarian": 13, "login_time": "2024-01-04T09:26:31.225Z"}}, {"model": "library.loginhistory", "pk": 32, "fields": {"librarian": 14, "login_time": "2024-01-04T09:43:28.611Z"}}, {"model": "library.loginhistory", "pk": 33, "fields": {"librarian": 14, "login_time": "2024-01-04T09:57:29.759Z"}}, {"model": "library.loginhistory", "pk": 34, "fields": {"librarian": 14, "login_time": "2024-01-04T09:57:59.410Z"}}, {"model": "library.loginhistory", "pk": 35, "fields": {"librarian": 16, "login_time": "2024-01-04T10:53:28.050Z"}}, {"model": "library.loginhistory", "pk": 36, "fields": {"librarian": 17, "login_time": "2024-01-04T10:54:39.704Z"}}, {"model": "library.loginhistory", "pk": 37, "fields": {"librarian": 5, "login_time": "2024-01-04T10:58:48.595Z"}}, {"model": "library.loginhistory", "pk": 38, "fields": {"librarian": 6, "login_time": "2024-01-04T10:59:10.323Z"}}, {"model": "library.loginhistory", "pk": 39, "fields": {"librarian": 5, "login_time": "2024-01-05T02:04:32.624Z"}}, {"model": "library.loginhistory", "pk": 40, "fields": {"librarian": 5, "login_time": "2024-01-05T02:11:46.808Z"}}, {"model": "library.loginhistory", "pk": 41, "fields": {"librarian": 14, "login_time": "2024-01-05T02:38:58.471Z"}}, {"model": "library.loginhistory", "pk": 42, "fields": {"librarian": 5, "login_time": "2024-01-05T04:00:01.200Z"}}, {"model": "library.loginhistory", "pk": 43, "fields": {"librarian": 14, "login_time": "2024-01-05T06:21:40.329Z"}}, {"model": "library.loginhistory", "pk": 44, "fields": {"librarian": 5, "login_time": "2024-01-05T06:28:56.624Z"}}, {"model": "library.loginhistory", "pk": 45, "fields": {"librarian": 5, "login_time": "2024-01-05T06:29:01.303Z"}}, {"model": "library.loginhistory", "pk": 46, "fields": {"librarian": 5, "login_time": "2024-01-05T06:31:03.831Z"}}, {"model": "library.loginhistory", "pk": 47, "fields": {"librarian": 14, "login_time": "2024-01-05T06:31:10.011Z"}}, {"model": "library.loginhistory", "pk": 48, "fields": {"librarian": 14, "login_time": "2024-01-05T06:33:31.016Z"}}, {"model": "library.loginhistory", "pk": 49, "fields": {"librarian": 14, "login_time": "2024-01-05T06:35:28.647Z"}}, {"model": "library.loginhistory", "pk": 50, "fields": {"librarian": 14, "login_time": "2024-01-05T06:36:43.665Z"}}, {"model": "library.loginhistory", "pk": 51, "fields": {"librarian": 14, "login_time": "2024-01-05T06:36:55.253Z"}}, {"model": "library.loginhistory", "pk": 52, "fields": {"librarian": 5, "login_time": "2024-01-05T06:48:27.621Z"}}, {"model": "library.loginhistory", "pk": 53, "fields": {"librarian": 5, "login_time": "2024-01-05T06:58:45.301Z"}}, {"model": "library.loginhistory", "pk": 54, "fields": {"librarian": 14, "login_time": "2024-01-05T06:58:57.391Z"}}, {"model": "library.loginhistory", "pk": 55, "fields": {"librarian": 18, "login_time": "2024-01-05T07:04:39.684Z"}}, {"model": "library.loginhistory", "pk": 56, "fields": {"librarian": 18, "login_time": "2024-01-05T07:06:50.077Z"}}, {"model": "library.loginhistory", "pk": 57, "fields": {"librarian": 5, "login_time": "2024-01-05T07:08:15.579Z"}}, {"model": "library.loginhistory", "pk": 58, "fields": {"librarian": 1, "login_time": "2024-01-05T07:08:38.562Z"}}, {"model": "library.loginhistory", "pk": 59, "fields": {"librarian": 1, "login_time": "2024-01-05T07:09:06.570Z"}}, {"model": "library.loginhistory", "pk": 60, "fields": {"librarian": 5, "login_time": "2024-01-05T07:09:49.738Z"}}, {"model": "library.loginhistory", "pk": 61, "fields": {"librarian": 1, "login_time": "2024-01-05T07:10:41.243Z"}}, {"model": "library.loginhistory", "pk": 62, "fields": {"librarian": 5, "login_time": "2024-01-05T07:15:58.745Z"}}, {"model": "library.loginhistory", "pk": 63, "fields": {"librarian": 19, "login_time": "2024-01-05T07:24:34.271Z"}}, {"model": "library.loginhistory", "pk": 64, "fields": {"librarian": 19, "login_time": "2024-01-05T07:24:47.851Z"}}, {"model": "library.loginhistory", "pk": 65, "fields": {"librarian": 5, "login_time": "2024-01-05T07:25:05.954Z"}}, {"model": "library.loginhistory", "pk": 66, "fields": {"librarian": 19, "login_time": "2024-01-05T07:26:35.425Z"}}, {"model": "library.loginhistory", "pk": 67, "fields": {"librarian": 5, "login_time": "2024-01-05T07:30:27.103Z"}}, {"model": "library.loginhistory", "pk": 68, "fields": {"librarian": 14, "login_time": "2024-01-05T07:31:29.038Z"}}, {"model": "library.loginhistory", "pk": 69, "fields": {"librarian": 5, "login_time": "2024-01-05T07:47:53.615Z"}}, {"model": "library.loginhistory", "pk": 70, "fields": {"librarian": 5, "login_time": "2024-01-05T07:49:29.087Z"}}, {"model": "library.loginhistory", "pk": 71, "fields": {"librarian": 14, "login_time": "2024-01-05T07:52:12.739Z"}}, {"model": "library.loginhistory", "pk": 72, "fields": {"librarian": 5, "login_time": "2024-01-05T08:12:43.949Z"}}, {"model": "library.loginhistory", "pk": 73, "fields": {"librarian": 14, "login_time": "2024-01-05T08:13:22.943Z"}}, {"model": "library.loginhistory", "pk": 74, "fields": {"librarian": 5, "login_time": "2024-01-05T08:14:10.729Z"}}, {"model": "library.loginhistory", "pk": 75, "fields": {"librarian": 14, "login_time": "2024-01-05T08:30:09.087Z"}}, {"model": "library.loginhistory", "pk": 76, "fields": {"librarian": 5, "login_time": "2024-01-05T08:34:38.146Z"}}, {"model": "library.loginhistory", "pk": 77, "fields": {"librarian": 20, "login_time": "2024-01-05T08:50:41.985Z"}}, {"model": "library.loginhistory", "pk": 78, "fields": {"librarian": 23, "login_time": "2024-01-05T09:25:01.102Z"}}, {"model": "library.loginhistory", "pk": 79, "fields": {"librarian": 24, "login_time": "2024-01-05T09:27:13.334Z"}}, {"model": "library.loginhistory", "pk": 80, "fields": {"librarian": 23, "login_time": "2024-01-05T09:32:21.147Z"}}, {"model": "library.loginhistory", "pk": 81, "fields": {"librarian": 5, "login_time": "2024-01-05T09:32:55.581Z"}}, {"model": "library.loginhistory", "pk": 82, "fields": {"librarian": 14, "login_time": "2024-01-05T09:34:17.606Z"}}, {"model": "library.loginhistory", "pk": 83, "fields": {"librarian": 14, "login_time": "2024-01-05T09:34:40.405Z"}}, {"model": "library.loginhistory", "pk": 84, "fields": {"librarian": 5, "login_time": "2024-01-05T10:38:09.466Z"}}, {"model": "library.loginhistory", "pk": 85, "fields": {"librarian": 5, "login_time": "2024-01-05T10:42:47.871Z"}}, {"model": "library.loginhistory", "pk": 86, "fields": {"librarian": 5, "login_time": "2024-01-05T11:05:01.155Z"}}, {"model": "library.loginhistory", "pk": 87, "fields": {"librarian": 5, "login_time": "2024-01-08T03:17:46.922Z"}}, {"model": "library.loginhistory", "pk": 88, "fields": {"librarian": 29, "login_time": "2024-01-09T07:25:11.103Z"}}, {"model": "library.loginhistory", "pk": 89, "fields": {"librarian": 14, "login_time": "2024-01-09T08:48:30.828Z"}}, {"model": "library.loginhistory", "pk": 90, "fields": {"librarian": 29, "login_time": "2024-01-09T08:52:28.915Z"}}, {"model": "library.loginhistory", "pk": 91, "fields": {"librarian": 29, "login_time": "2024-01-10T06:49:57.892Z"}}, {"model": "library.loginhistory", "pk": 92, "fields": {"librarian": 29, "login_time": "2024-01-10T07:05:01.553Z"}}, {"model": "library.loginhistory", "pk": 93, "fields": {"librarian": 5, "login_time": "2024-01-12T03:33:34.738Z"}}, {"model": "library.loginhistory", "pk": 94, "fields": {"librarian": 5, "login_time": "2024-01-12T07:06:27.410Z"}}, {"model": "library.loginhistory", "pk": 95, "fields": {"librarian": 5, "login_time": "2024-01-12T07:10:31.583Z"}}, {"model": "authtoken.token", "pk": "927f8e91cd8cd4b144dc0721bec64bc30e6a025c", "fields": {"user": 6, "created": "2024-01-04T03:50:55.419Z"}}, {"model": "authtoken.token", "pk": "9b1774fb8142f29a4d7c4e1f6f04c2421435d876", "fields": {"user": 5, "created": "2024-01-04T04:33:06.756Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 1, "fields": {"user": 5, "jti": "1106ad756a6848e383e307d201698c90", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0MzM3MiwiaWF0IjoxNzA0MzU2OTcyLCJqdGkiOiIxMTA2YWQ3NTZhNjg0OGUzODNlMzA3ZDIwMTY5OGM5MCIsInVzZXJfaWQiOjV9.rk03eQG4RwEuvvCGIichT6ZkiXvsw60y_W2J5HytdQg", "created_at": "2024-01-04T08:29:32.680Z", "expires_at": "2024-01-05T08:29:32Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 2, "fields": {"user": 5, "jti": "57191e8023044a088c760f1d21ed5ee9", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0MzcxOSwiaWF0IjoxNzA0MzU3MzE5LCJqdGkiOiI1NzE5MWU4MDIzMDQ0YTA4OGM3NjBmMWQyMWVkNWVlOSIsInVzZXJfaWQiOjV9.mvs7pYA4QhdfYAuBdkXW2bO17a4e_6rv7jmTbduaZ5s", "created_at": "2024-01-04T08:35:19.642Z", "expires_at": "2024-01-05T08:35:19Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 3, "fields": {"user": 5, "jti": "da98077f60aa4e078857eb7aba6ff313", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0Mzc4OSwiaWF0IjoxNzA0MzU3Mzg5LCJqdGkiOiJkYTk4MDc3ZjYwYWE0ZTA3ODg1N2ViN2FiYTZmZjMxMyIsInVzZXJfaWQiOjV9.C4zIXVbH8KfNHM2CYbP1u6e_WeVKbVT6geTlW4JmAhI", "created_at": "2024-01-04T08:36:29.897Z", "expires_at": "2024-01-05T08:36:29Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 4, "fields": {"user": 5, "jti": "d50d82db24094b9d8641ba6a19196c87", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0NDE4MCwiaWF0IjoxNzA0MzU3NzgwLCJqdGkiOiJkNTBkODJkYjI0MDk0YjlkODY0MWJhNmExOTE5NmM4NyIsInVzZXJfaWQiOjV9.OZD8EMWLZO3dV2tERgvTkaXpuyUW04f9Nkf57IANMqo", "created_at": "2024-01-04T08:43:00.828Z", "expires_at": "2024-01-05T08:43:00Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 5, "fields": {"user": 5, "jti": "bd4a23ab7acc4b34a4a3629a789ff923", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0Nzk2MywiaWF0IjoxNzA0MzYxNTYzLCJqdGkiOiJiZDRhMjNhYjdhY2M0YjM0YTRhMzYyOWE3ODlmZjkyMyIsInVzZXJfaWQiOjV9._qm4YVqb-HZ2OpGRrT7oLWVHM319Y3x5WCKlCWgg24E", "created_at": "2024-01-04T09:46:03.637Z", "expires_at": "2024-01-05T09:46:03Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 6, "fields": {"user": 6, "jti": "f198982adf514f15bb339f5126dc22d6", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0ODU5MSwiaWF0IjoxNzA0MzYyMTkxLCJqdGkiOiJmMTk4OTgyYWRmNTE0ZjE1YmIzMzlmNTEyNmRjMjJkNiIsInVzZXJfaWQiOjZ9.vtOlas1GnkrIlk9JEocsIoKuzEWcMw-W_NxcSmn8LVk", "created_at": "2024-01-04T09:56:31.667Z", "expires_at": "2024-01-05T09:56:31Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 7, "fields": {"user": 15, "jti": "fcb5160e901643fc902ee8ae14620efc", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDQ0OTA0MCwiaWF0IjoxNzA0MzYyNjQwLCJqdGkiOiJmY2I1MTYwZTkwMTY0M2ZjOTAyZWU4YWUxNDYyMGVmYyIsInVzZXJfaWQiOjE1fQ.IC_h534_A4ZC_BGiGP07fGfea_bNB7m5XPJ1P_UcKSo", "created_at": "2024-01-04T10:04:00.499Z", "expires_at": "2024-01-05T10:04:00Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 8, "fields": {"user": 5, "jti": "52a83cb8634748399d8d48874e924e04", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzIzMCwiaWF0IjoxNzA0NDIwODMwLCJqdGkiOiI1MmE4M2NiODYzNDc0ODM5OWQ4ZDQ4ODc0ZTkyNGUwNCIsInVzZXJfaWQiOjV9.d40j87DQf3KjN_fJ0tFmZVUpr9aX4SOsfhEXHwdnt7Q", "created_at": "2024-01-05T02:13:50.194Z", "expires_at": "2024-01-06T02:13:50Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 9, "fields": {"user": 14, "jti": "cf706ac191034ca9b2bb11d1e8d148d6", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzI0NywiaWF0IjoxNzA0NDIwODQ3LCJqdGkiOiJjZjcwNmFjMTkxMDM0Y2E5YjJiYjExZDFlOGQxNDhkNiIsInVzZXJfaWQiOjE0fQ.jz-tDiy86eU1tEI_nFi08jOh4G-lZz7rQMp9hZwFwbc", "created_at": "2024-01-05T02:14:07.407Z", "expires_at": "2024-01-06T02:14:07Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 10, "fields": {"user": 14, "jti": "2f8ab4973051467aa739f5933b9b87a0", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzM0MiwiaWF0IjoxNzA0NDIwOTQyLCJqdGkiOiIyZjhhYjQ5NzMwNTE0NjdhYTczOWY1OTMzYjliODdhMCIsInVzZXJfaWQiOjE0fQ.QePLtCWG3JCXYvkXaWFQc9T2vBdhuwsiPBvwOQ3VnIY", "created_at": "2024-01-05T02:15:42.541Z", "expires_at": "2024-01-06T02:15:42Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 11, "fields": {"user": 14, "jti": "d5769646f0a4437284f1220154758e2e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzYwOSwiaWF0IjoxNzA0NDIxMjA5LCJqdGkiOiJkNTc2OTY0NmYwYTQ0MzcyODRmMTIyMDE1NDc1OGUyZSIsInVzZXJfaWQiOjE0fQ.1jriE0ej93Ku3gpNmrzRyWEyHp5zzajjl1u0frrwkNI", "created_at": "2024-01-05T02:20:09.456Z", "expires_at": "2024-01-06T02:20:09Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 12, "fields": {"user": 14, "jti": "1dba02f54c5e4fcc9c2c967eabf196b5", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzg2MCwiaWF0IjoxNzA0NDIxNDYwLCJqdGkiOiIxZGJhMDJmNTRjNWU0ZmNjOWMyYzk2N2VhYmYxOTZiNSIsInVzZXJfaWQiOjE0fQ.pXvo70N1l1ODaDV05NYT4hDrdx27coP6c5dDl6fICsw", "created_at": "2024-01-05T02:24:20.471Z", "expires_at": "2024-01-06T02:24:20Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 13, "fields": {"user": 5, "jti": "88d65f0e7d7048a6aff595f0792ee013", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwNzkxOSwiaWF0IjoxNzA0NDIxNTE5LCJqdGkiOiI4OGQ2NWYwZTdkNzA0OGE2YWZmNTk1ZjA3OTJlZTAxMyIsInVzZXJfaWQiOjV9.wMucvZnYf13si1cjFir6h7ezXXqYzH-u0UgV52Ychn4", "created_at": "2024-01-05T02:25:19.490Z", "expires_at": "2024-01-06T02:25:19Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 14, "fields": {"user": 5, "jti": "e0913e92f0cc4c4f9970aafbb765de97", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwODI2NSwiaWF0IjoxNzA0NDIxODY1LCJqdGkiOiJlMDkxM2U5MmYwY2M0YzRmOTk3MGFhZmJiNzY1ZGU5NyIsInVzZXJfaWQiOjV9.a7jCXCaC1ePYYevdOsfIjPOuVhy9W65pA1rZMD-c-p8", "created_at": "2024-01-05T02:31:05.999Z", "expires_at": "2024-01-06T02:31:05Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 15, "fields": {"user": 14, "jti": "fba4e5f6c66d47fdab529319f831abe6", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUwODMxNywiaWF0IjoxNzA0NDIxOTE3LCJqdGkiOiJmYmE0ZTVmNmM2NmQ0N2ZkYWI1MjkzMTlmODMxYWJlNiIsInVzZXJfaWQiOjE0fQ.OTFpXMHXnwDY8qB_3yxWG1xwAvAQjswE4-ncaew5cZA", "created_at": "2024-01-05T02:31:57.756Z", "expires_at": "2024-01-06T02:31:57Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 16, "fields": {"user": 5, "jti": "2f64d904651749e08c1a2bc07f85ee51", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUxNDM1NywiaWF0IjoxNzA0NDI3OTU3LCJqdGkiOiIyZjY0ZDkwNDY1MTc0OWUwOGMxYTJiYzA3Zjg1ZWU1MSIsInVzZXJfaWQiOjV9.kr3vY8ab6fbRgqg5Mwyqbvj0oKGYPru7OfKkR9JRcHs", "created_at": "2024-01-05T04:12:37.948Z", "expires_at": "2024-01-06T04:12:37Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 17, "fields": {"user": 5, "jti": "5f134c65c43e400aa992b1ff9492b72b", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUxNDM5OSwiaWF0IjoxNzA0NDI3OTk5LCJqdGkiOiI1ZjEzNGM2NWM0M2U0MDBhYTk5MmIxZmY5NDkyYjcyYiIsInVzZXJfaWQiOjV9.Wn9v8NvY50DLlXO2zpABi2sKlEvlmOdSPl0SbWK1pPo", "created_at": "2024-01-05T04:13:19.064Z", "expires_at": "2024-01-06T04:13:19Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 18, "fields": {"user": 14, "jti": "e6b3a52b86954e0896fc8c3384f29b37", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUxNDQ0NiwiaWF0IjoxNzA0NDI4MDQ2LCJqdGkiOiJlNmIzYTUyYjg2OTU0ZTA4OTZmYzhjMzM4NGYyOWIzNyIsInVzZXJfaWQiOjE0fQ.YrWWUbXIESgydIZeg8RfL_8GSVj2QipsxeAXYJrKqoo", "created_at": "2024-01-05T04:14:06.474Z", "expires_at": "2024-01-06T04:14:06Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 19, "fields": {"user": 5, "jti": "1221f8bbba754fda9f9cb6c0ebb2f105", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUxNDUzOCwiaWF0IjoxNzA0NDI4MTM4LCJqdGkiOiIxMjIxZjhiYmJhNzU0ZmRhOWY5Y2I2YzBlYmIyZjEwNSIsInVzZXJfaWQiOjV9.C8taBah937BfJ7HSkEG-wE4eHe1XLqZJU-zw17lgPWE", "created_at": "2024-01-05T04:15:38.401Z", "expires_at": "2024-01-06T04:15:38Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 20, "fields": {"user": 5, "jti": "8d4eae2ba8ad4ff7833bef43d8de52a1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUyOTAwNywiaWF0IjoxNzA0NDQyNjA3LCJqdGkiOiI4ZDRlYWUyYmE4YWQ0ZmY3ODMzYmVmNDNkOGRlNTJhMSIsInVzZXJfaWQiOjV9.JNup4IOBqUb-pZGQMdbM9cR_0VG39ug4ohNl2g8HFPs", "created_at": "2024-01-05T08:16:47.129Z", "expires_at": "2024-01-06T08:16:47Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 21, "fields": {"user": 14, "jti": "3f51e30919ac440ca581ec2bf7a32bc2", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUyOTIxNCwiaWF0IjoxNzA0NDQyODE0LCJqdGkiOiIzZjUxZTMwOTE5YWM0NDBjYTU4MWVjMmJmN2EzMmJjMiIsInVzZXJfaWQiOjE0fQ.Iya0YMnqv_Uhaa3Fzf_m8PPwPnpxChGIh3Xc_XnzLCk", "created_at": "2024-01-05T08:20:14.603Z", "expires_at": "2024-01-06T08:20:14Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 22, "fields": {"user": 14, "jti": "eecfa23127174b12a4236399fbe92457", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzNzAyOSwiaWF0IjoxNzA0NDUwNjI5LCJqdGkiOiJlZWNmYTIzMTI3MTc0YjEyYTQyMzYzOTlmYmU5MjQ1NyIsInVzZXJfaWQiOjE0fQ.teoQVltWJCVc4SU2V-wypFnxZeUMKJQ0dDUomc33Cus", "created_at": "2024-01-05T10:30:29.882Z", "expires_at": "2024-01-06T10:30:29Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 23, "fields": {"user": 5, "jti": "8af58df9087d468cbcb69400655a8762", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzNzc5MiwiaWF0IjoxNzA0NDUxMzkyLCJqdGkiOiI4YWY1OGRmOTA4N2Q0NjhjYmNiNjk0MDA2NTVhODc2MiIsInVzZXJfaWQiOjV9.BXpZsBiSODntbvhnq29puhDiJ-Bz1EcQczMfbiHJz-Y", "created_at": "2024-01-05T10:43:12.327Z", "expires_at": "2024-01-06T10:43:12Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 24, "fields": {"user": 5, "jti": "c79c47eda902422d8d05f6707f73355e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzNzk0MiwiaWF0IjoxNzA0NDUxNTQyLCJqdGkiOiJjNzljNDdlZGE5MDI0MjJkOGQwNWY2NzA3ZjczMzU1ZSIsInVzZXJfaWQiOjV9.JmvUzaViVce3rTxOFZmTlbi9-QB5blgnDUVgidmZE4Q", "created_at": "2024-01-05T10:45:42.686Z", "expires_at": "2024-01-06T10:45:42Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 25, "fields": {"user": 25, "jti": "71b3ce210ec148c290a22457673b910b", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzODQ5MCwiaWF0IjoxNzA0NDUyMDkwLCJqdGkiOiI3MWIzY2UyMTBlYzE0OGMyOTBhMjI0NTc2NzNiOTEwYiIsInVzZXJfaWQiOjI1fQ.W7jjkNP_Xfl-HF2vuSzTKecXQPqkK9mND2DteNpQP8w", "created_at": "2024-01-05T10:54:50.845Z", "expires_at": "2024-01-06T10:54:50Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 26, "fields": {"user": 5, "jti": "85b0e4109fd84afea135fdee824ed5fb", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzOTE5OCwiaWF0IjoxNzA0NDUyNzk4LCJqdGkiOiI4NWIwZTQxMDlmZDg0YWZlYTEzNWZkZWU4MjRlZDVmYiIsInVzZXJfaWQiOjV9.jvpqgTbfzSOGWYILgdSdKeCNX31plDZ8tx7jjFFPfqE", "created_at": "2024-01-05T11:06:38.376Z", "expires_at": "2024-01-06T11:06:38Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 27, "fields": {"user": 25, "jti": "9d2c109fc8c14ca791f54ebed7d5070b", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzOTQ0MywiaWF0IjoxNzA0NDUzMDQzLCJqdGkiOiI5ZDJjMTA5ZmM4YzE0Y2E3OTFmNTRlYmVkN2Q1MDcwYiIsInVzZXJfaWQiOjI1fQ.NZTqFLtb8T98uDQsT7YSk0x9rKf13q0_FSOYTFPERzk", "created_at": "2024-01-05T11:10:43.360Z", "expires_at": "2024-01-06T11:10:43Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 28, "fields": {"user": 5, "jti": "2c275d64cb054b32b373a49f19cb0607", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzOTUwNSwiaWF0IjoxNzA0NDUzMTA1LCJqdGkiOiIyYzI3NWQ2NGNiMDU0YjMyYjM3M2E0OWYxOWNiMDYwNyIsInVzZXJfaWQiOjV9.C_rVaohBT2riBwIFlVF7eOupSewIicCOOp3W6dWkRfk", "created_at": "2024-01-05T11:11:45.373Z", "expires_at": "2024-01-06T11:11:45Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 29, "fields": {"user": 25, "jti": "f7a5c03bfc924edab1f4f279cddd5cf3", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzOTU3NywiaWF0IjoxNzA0NDUzMTc3LCJqdGkiOiJmN2E1YzAzYmZjOTI0ZWRhYjFmNGYyNzljZGRkNWNmMyIsInVzZXJfaWQiOjI1fQ.znAMmrQz2Pdul2EQtX91PmKWLKUb15ZNoBpG45UTlTc", "created_at": "2024-01-05T11:12:57.272Z", "expires_at": "2024-01-06T11:12:57Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 30, "fields": {"user": 5, "jti": "383a56471fad47d4a6896cbd62f5b3f1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDUzOTY2NSwiaWF0IjoxNzA0NDUzMjY1LCJqdGkiOiIzODNhNTY0NzFmYWQ0N2Q0YTY4OTZjYmQ2MmY1YjNmMSIsInVzZXJfaWQiOjV9.72t51ttWCoLIo7EpXde8Gnlmu5OIgpIc0w_8pdQIebc", "created_at": "2024-01-05T11:14:25.034Z", "expires_at": "2024-01-06T11:14:25Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 31, "fields": {"user": 26, "jti": "d871fa62404246cf8574c15200dd32d7", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDU0MDI2MywiaWF0IjoxNzA0NDUzODYzLCJqdGkiOiJkODcxZmE2MjQwNDI0NmNmODU3NGMxNTIwMGRkMzJkNyIsInVzZXJfaWQiOjI2fQ.5JGef5hAjn1-_toK2NgGiEkdcgl61R4XZ5xmC7RW9RA", "created_at": "2024-01-05T11:24:23.436Z", "expires_at": "2024-01-06T11:24:23Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 32, "fields": {"user": 26, "jti": "d34e73a92cf94985b976e883a32255c6", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDU0MDQxMSwiaWF0IjoxNzA0NDU0MDExLCJqdGkiOiJkMzRlNzNhOTJjZjk0OTg1Yjk3NmU4ODNhMzIyNTVjNiIsInVzZXJfaWQiOjI2fQ.kHFF4hIvabIZiTtup7J7O5J6CLagBTQZM0agFL34W1Y", "created_at": "2024-01-05T11:26:51.422Z", "expires_at": "2024-01-06T11:26:51Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 33, "fields": {"user": 5, "jti": "e3f65af9793f42958fd42788b646b0fb", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDU0MDQ0MiwiaWF0IjoxNzA0NDU0MDQyLCJqdGkiOiJlM2Y2NWFmOTc5M2Y0Mjk1OGZkNDI3ODhiNjQ2YjBmYiIsInVzZXJfaWQiOjV9.bqL9XV0ShCH5Ik50NqP9HGUcZL5-oLW7kqFCYBWRDv0", "created_at": "2024-01-05T11:27:22.982Z", "expires_at": "2024-01-06T11:27:22Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 34, "fields": {"user": 27, "jti": "62b5934ec49a45f6a6b796e9146dd40e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDU0MTU1NCwiaWF0IjoxNzA0NDU1MTU0LCJqdGkiOiI2MmI1OTM0ZWM0OWE0NWY2YTZiNzk2ZTkxNDZkZDQwZSIsInVzZXJfaWQiOjI3fQ.oQy9sRGxS2R-rpw1JeET9cTYz69nevXw8n64DXQaUV0", "created_at": "2024-01-05T11:45:54.850Z", "expires_at": "2024-01-06T11:45:54Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 35, "fields": {"user": 27, "jti": "773768bb79964ebc942e558c53b7e29f", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDU0MTkwMiwiaWF0IjoxNzA0NDU1NTAyLCJqdGkiOiI3NzM3NjhiYjc5OTY0ZWJjOTQyZTU1OGM1M2I3ZTI5ZiIsInVzZXJfaWQiOjI3fQ.1FcH_ILoa7cX1hAFzccbcFo2DMLgBpQ2OIW-klPLSPk", "created_at": "2024-01-05T11:51:42.327Z", "expires_at": "2024-01-06T11:51:42Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 36, "fields": {"user": 28, "jti": "9a62923c37b44e8da33322e1fb00d9ea", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2NzU4MCwiaWF0IjoxNzA0NjgxMTgwLCJqdGkiOiI5YTYyOTIzYzM3YjQ0ZThkYTMzMzIyZTFmYjAwZDllYSIsInVzZXJfaWQiOjI4fQ.kp6BfprFLOwAW4sbiuRQUFbZEgiJilvXkJbLP-L9Idk", "created_at": "2024-01-08T02:33:00.381Z", "expires_at": "2024-01-09T02:33:00Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 37, "fields": {"user": 29, "jti": "1b716bf7f11d4efda5156e1772569d11", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2ODE4NiwiaWF0IjoxNzA0NjgxNzg2LCJqdGkiOiIxYjcxNmJmN2YxMWQ0ZWZkYTUxNTZlMTc3MjU2OWQxMSIsInVzZXJfaWQiOjI5fQ.Bgk-24VSJztwUR9p6yWnSY5MpnrJGjPi1DCMr1sixDw", "created_at": "2024-01-08T02:43:06.493Z", "expires_at": "2024-01-09T02:43:06Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 38, "fields": {"user": 29, "jti": "83a0598fa52a466fb75c37bfe68e3dbd", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2ODgxMiwiaWF0IjoxNzA0NjgyNDEyLCJqdGkiOiI4M2EwNTk4ZmE1MmE0NjZmYjc1YzM3YmZlNjhlM2RiZCIsInVzZXJfaWQiOjI5fQ.wgxb0IA-N4rYW5ZIci0LhPpA08ttAuOpXFP0u7gCyq4", "created_at": "2024-01-08T02:53:32.876Z", "expires_at": "2024-01-09T02:53:32Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 39, "fields": {"user": 29, "jti": "7560f8aeb04948e5933ba8821e5add8a", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2ODg3OCwiaWF0IjoxNzA0NjgyNDc4LCJqdGkiOiI3NTYwZjhhZWIwNDk0OGU1OTMzYmE4ODIxZTVhZGQ4YSIsInVzZXJfaWQiOjI5fQ.g_YJzKfASHtETvIh3FGdjLkIk51iMoFp8YhjHOeaMBw", "created_at": "2024-01-08T02:54:38.134Z", "expires_at": "2024-01-09T02:54:38Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 40, "fields": {"user": 29, "jti": "c335a97044bf440fb397f06d3aeecb3a", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2ODg5OSwiaWF0IjoxNzA0NjgyNDk5LCJqdGkiOiJjMzM1YTk3MDQ0YmY0NDBmYjM5N2YwNmQzYWVlY2IzYSIsInVzZXJfaWQiOjI5fQ._sG8GevCmbGOPV8hctFrHhIuxmijsvEigdp3KFuj8KA", "created_at": "2024-01-08T02:54:59.413Z", "expires_at": "2024-01-09T02:54:59Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 41, "fields": {"user": 29, "jti": "fbf79eb3bb6a4a43a64110165b314e12", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2ODkxOSwiaWF0IjoxNzA0NjgyNTE5LCJqdGkiOiJmYmY3OWViM2JiNmE0YTQzYTY0MTEwMTY1YjMxNGUxMiIsInVzZXJfaWQiOjI5fQ.JIN2kTbzBNla5zqdvfBf2DwCWUQp50crern0-KuiKWk", "created_at": "2024-01-08T02:55:19.396Z", "expires_at": "2024-01-09T02:55:19Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 42, "fields": {"user": 29, "jti": "ad124bcbadb645e19ac28e0485a30cde", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2OTI0NiwiaWF0IjoxNzA0NjgyODQ2LCJqdGkiOiJhZDEyNGJjYmFkYjY0NWUxOWFjMjhlMDQ4NWEzMGNkZSIsInVzZXJfaWQiOjI5fQ.V9rshCdDlWmErskykkgOhp3V8fKnnU0RMCUZlsmrc9c", "created_at": "2024-01-08T03:00:46.013Z", "expires_at": "2024-01-09T03:00:46Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 43, "fields": {"user": 29, "jti": "aa7544b9e480420ea177b2319778c32e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc2OTU5OSwiaWF0IjoxNzA0NjgzMTk5LCJqdGkiOiJhYTc1NDRiOWU0ODA0MjBlYTE3N2IyMzE5Nzc4YzMyZSIsInVzZXJfaWQiOjI5fQ.S3lGIMwn8uoSl-xy5jSo1F0gGW-9NIDq-2jEy1izLJw", "created_at": "2024-01-08T03:06:39.359Z", "expires_at": "2024-01-09T03:06:39Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 44, "fields": {"user": 29, "jti": "0ba9a9fef0844e94a12cd97c03b653e5", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc3MDIzMywiaWF0IjoxNzA0NjgzODMzLCJqdGkiOiIwYmE5YTlmZWYwODQ0ZTk0YTEyY2Q5N2MwM2I2NTNlNSIsInVzZXJfaWQiOjI5fQ.rHb4UXVOME6ar-jGtVGismyqnDPDW_uyzv5yyTX5_bk", "created_at": "2024-01-08T03:17:13.086Z", "expires_at": "2024-01-09T03:17:13Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 45, "fields": {"user": 28, "jti": "ca8f96bc134c48f9b472acbe2bdaa08b", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc3MjAyNiwiaWF0IjoxNzA0Njg1NjI2LCJqdGkiOiJjYThmOTZiYzEzNGM0OGY5YjQ3MmFjYmUyYmRhYTA4YiIsInVzZXJfaWQiOjI4fQ.yFLzofFTHpWpE_Bmuvl7MlpcsuIzBXbjEIVO6zarHl4", "created_at": "2024-01-08T03:47:06.858Z", "expires_at": "2024-01-09T03:47:06Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 46, "fields": {"user": 28, "jti": "0291d2218f184406ba07b5c8d573312e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc3MjM5NSwiaWF0IjoxNzA0Njg1OTk1LCJqdGkiOiIwMjkxZDIyMThmMTg0NDA2YmEwN2I1YzhkNTczMzEyZSIsInVzZXJfaWQiOjI4fQ.UPjcCrGEZt9bacjYAeUBlugHRBOkNHOxpNgNTGLQsPo", "created_at": "2024-01-08T03:53:15.786Z", "expires_at": "2024-01-09T03:53:15Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 47, "fields": {"user": 28, "jti": "bb6d24bdbe4d42f2ba811d11a551000c", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc3MjY2OCwiaWF0IjoxNzA0Njg2MjY4LCJqdGkiOiJiYjZkMjRiZGJlNGQ0MmYyYmE4MTFkMTFhNTUxMDAwYyIsInVzZXJfaWQiOjI4fQ.O6-8BTK1zIyL7IESGH_aXkNNVMA41GQPZpv82pXrq0Y", "created_at": "2024-01-08T03:57:48.759Z", "expires_at": "2024-01-09T03:57:48Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 48, "fields": {"user": 29, "jti": "97da8cdc638c47a0b50f60a4928caac1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc4MTIyOCwiaWF0IjoxNzA0Njk0ODI4LCJqdGkiOiI5N2RhOGNkYzYzOGM0N2EwYjUwZjYwYTQ5MjhjYWFjMSIsInVzZXJfaWQiOjI5fQ.anG2Jq4y6FCJlXtmr_vNhkygs3G14ajEPejvh6IaGvE", "created_at": "2024-01-08T06:20:28.996Z", "expires_at": "2024-01-09T06:20:28Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 49, "fields": {"user": 29, "jti": "36b96e7813414d138878bb39cf9dbf5c", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDc4Njg1MiwiaWF0IjoxNzA0NzAwNDUyLCJqdGkiOiIzNmI5NmU3ODEzNDE0ZDEzODg3OGJiMzljZjlkYmY1YyIsInVzZXJfaWQiOjI5fQ.sJML_fCTQKdh_C2JMb4fKUUJuWqoOPVYHmPK7O-_fG4", "created_at": "2024-01-08T07:54:12.945Z", "expires_at": "2024-01-09T07:54:12Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 50, "fields": {"user": 28, "jti": "df4eff50e908404491875c0ab862316c", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDg1NTc0NSwiaWF0IjoxNzA0NzY5MzQ1LCJqdGkiOiJkZjRlZmY1MGU5MDg0MDQ0OTE4NzVjMGFiODYyMzE2YyIsInVzZXJfaWQiOjI4fQ.owHQYkdXQ5gymsBxAIhPkKldaV84jrrdMIcXOcVS2gs", "created_at": "2024-01-09T03:02:25.282Z", "expires_at": "2024-01-10T03:02:25Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 51, "fields": {"user": 29, "jti": "8b14fc3bedc341758aff365104577aac", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDg1NTc4OSwiaWF0IjoxNzA0NzY5Mzg5LCJqdGkiOiI4YjE0ZmMzYmVkYzM0MTc1OGFmZjM2NTEwNDU3N2FhYyIsInVzZXJfaWQiOjI5fQ.ZpgFwxh65DWTk8l8uswp3Enbqzq9VAOtBqU2L7a_ScM", "created_at": "2024-01-09T03:03:09.359Z", "expires_at": "2024-01-10T03:03:09Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 52, "fields": {"user": 29, "jti": "0b084ced46a24e9d94733a0ad4e09d8e", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDk2MDAzOCwiaWF0IjoxNzA0ODczNjM4LCJqdGkiOiIwYjA4NGNlZDQ2YTI0ZTlkOTQ3MzNhMGFkNGUwOWQ4ZSIsInVzZXJfaWQiOjI5fQ.x3Wv3SR4HRqagZT-UuakYS70HNHn2dDRt5njM-X-PnM", "created_at": "2024-01-10T08:00:38.466Z", "expires_at": "2024-01-11T08:00:38Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 53, "fields": {"user": 29, "jti": "8eedc8b0927c4626a759816f88611ce7", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDk2MDg3MSwiaWF0IjoxNzA0ODc0NDcxLCJqdGkiOiI4ZWVkYzhiMDkyN2M0NjI2YTc1OTgxNmY4ODYxMWNlNyIsInVzZXJfaWQiOjI5fQ.5xSksmet5N-l11ZfG1aEm_62LpdR3Lr5-E_C8hv1mCA", "created_at": "2024-01-10T08:14:31.939Z", "expires_at": "2024-01-11T08:14:31Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 54, "fields": {"user": 29, "jti": "27a429f138714dd3acbf2418ce65cc8a", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDk2MTI0MywiaWF0IjoxNzA0ODc0ODQzLCJqdGkiOiIyN2E0MjlmMTM4NzE0ZGQzYWNiZjI0MThjZTY1Y2M4YSIsInVzZXJfaWQiOjI5fQ.UIDTHJfoif7rvt9mP2mEQcU0ALa31avoRo0SdPVOCro", "created_at": "2024-01-10T08:20:43.548Z", "expires_at": "2024-01-11T08:20:43Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 55, "fields": {"user": 29, "jti": "d46aee567cdd4077912d8617d453ed2f", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDk2MTYxNSwiaWF0IjoxNzA0ODc1MjE1LCJqdGkiOiJkNDZhZWU1NjdjZGQ0MDc3OTEyZDg2MTdkNDUzZWQyZiIsInVzZXJfaWQiOjI5fQ.wJk_WQ6Wj6uc2nQh1DwR8B0fYcWophk5JdskY1nPcag", "created_at": "2024-01-10T08:26:55.015Z", "expires_at": "2024-01-11T08:26:55Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 56, "fields": {"user": 29, "jti": "6c6052f8eb4e43bf93f06859fab7d239", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNDk2MjEyMCwiaWF0IjoxNzA0ODc1NzIwLCJqdGkiOiI2YzYwNTJmOGViNGU0M2JmOTNmMDY4NTlmYWI3ZDIzOSIsInVzZXJfaWQiOjI5fQ.Wgi3oDBH2HnuZY4jICopNcuXZuR4mQGJbJuHoUOGNUk", "created_at": "2024-01-10T08:35:20.041Z", "expires_at": "2024-01-11T08:35:20Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 57, "fields": {"user": 28, "jti": "a7fa0eb121d44018b63477a06172bf33", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNDk1NywiaWF0IjoxNzA1MDI4NTU3LCJqdGkiOiJhN2ZhMGViMTIxZDQ0MDE4YjYzNDc3YTA2MTcyYmYzMyIsInVzZXJfaWQiOjI4fQ.2yNMrUme6kvE-IgwK1aXVhxmUF4SmKHOneYKtL5zkTo", "created_at": "2024-01-12T03:02:37.700Z", "expires_at": "2024-01-13T03:02:37Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 58, "fields": {"user": 28, "jti": "682f96a5053d470f97ae95fd3b4aa0cc", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNTA1MSwiaWF0IjoxNzA1MDI4NjUxLCJqdGkiOiI2ODJmOTZhNTA1M2Q0NzBmOTdhZTk1ZmQzYjRhYTBjYyIsInVzZXJfaWQiOjI4fQ.iPuZsCP2dVvJFnXxL_CtmXgJt8pzwuY6fbMgNFbKMto", "created_at": "2024-01-12T03:04:11.031Z", "expires_at": "2024-01-13T03:04:11Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 59, "fields": {"user": 28, "jti": "6d803a1535e944cab676c31714621662", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNTI3MiwiaWF0IjoxNzA1MDI4ODcyLCJqdGkiOiI2ZDgwM2ExNTM1ZTk0NGNhYjY3NmMzMTcxNDYyMTY2MiIsInVzZXJfaWQiOjI4fQ.VP5ZZ3QRnLcy25mYZ2SPl_iPRsbLWmc8qN4BXOfh6O8", "created_at": "2024-01-12T03:07:52.259Z", "expires_at": "2024-01-13T03:07:52Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 60, "fields": {"user": 28, "jti": "ed52079f345c416294e14955e9173b23", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNTM2OSwiaWF0IjoxNzA1MDI4OTY5LCJqdGkiOiJlZDUyMDc5ZjM0NWM0MTYyOTRlMTQ5NTVlOTE3M2IyMyIsInVzZXJfaWQiOjI4fQ.WKUlwyDkiqyATbMNT7KzEqgV7j90ib9l3aL_LRObnzo", "created_at": "2024-01-12T03:09:29.369Z", "expires_at": "2024-01-13T03:09:29Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 61, "fields": {"user": 28, "jti": "d6cfa181abab438c9cd230c26ca67866", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNTQ3MCwiaWF0IjoxNzA1MDI5MDcwLCJqdGkiOiJkNmNmYTE4MWFiYWI0MzhjOWNkMjMwYzI2Y2E2Nzg2NiIsInVzZXJfaWQiOjI4fQ.Ua7RWwaBaiXG6dRPMbFCJaymBmuAAJu1aX-qb6vcPmE", "created_at": "2024-01-12T03:11:10.968Z", "expires_at": "2024-01-13T03:11:10Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 62, "fields": {"user": 28, "jti": "9e35d3b4d4884d068ccd90e54b6bd195", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNTg3NywiaWF0IjoxNzA1MDI5NDc3LCJqdGkiOiI5ZTM1ZDNiNGQ0ODg0ZDA2OGNjZDkwZTU0YjZiZDE5NSIsInVzZXJfaWQiOjI4fQ.EebtzRMebVxkz9IvcNacRJjcSl8ooe5L2CITidLrMdY", "created_at": "2024-01-12T03:17:57.006Z", "expires_at": "2024-01-13T03:17:57Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 63, "fields": {"user": 28, "jti": "ae31f77414f54f8eb952b26867595ef0", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNjIwNSwiaWF0IjoxNzA1MDI5ODA1LCJqdGkiOiJhZTMxZjc3NDE0ZjU0ZjhlYjk1MmIyNjg2NzU5NWVmMCIsInVzZXJfaWQiOjI4fQ.D1ZW4T-7F2K1_haeT2RwwWuuqzHlBYQx3nMrpcagjeY", "created_at": "2024-01-12T03:23:25.210Z", "expires_at": "2024-01-13T03:23:25Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 64, "fields": {"user": 28, "jti": "e5f8bdd0796e4faeab35ef1ae4aacf7f", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNjU0NSwiaWF0IjoxNzA1MDMwMTQ1LCJqdGkiOiJlNWY4YmRkMDc5NmU0ZmFlYWIzNWVmMWFlNGFhY2Y3ZiIsInVzZXJfaWQiOjI4fQ.vQYAZj-_EmxjJfcTrytxP8Q9FFxDupU7BT4ls5cWHBk", "created_at": "2024-01-12T03:29:05.866Z", "expires_at": "2024-01-13T03:29:05Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 65, "fields": {"user": 28, "jti": "d751726d729b41b49724c206db3099f4", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNjk1MiwiaWF0IjoxNzA1MDMwNTUyLCJqdGkiOiJkNzUxNzI2ZDcyOWI0MWI0OTcyNGMyMDZkYjMwOTlmNCIsInVzZXJfaWQiOjI4fQ.R26U0AGYKsOsq8quzjrsh4Rk9OzewMr2IHXqkhyU_0g", "created_at": "2024-01-12T03:35:52.130Z", "expires_at": "2024-01-13T03:35:52Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 66, "fields": {"user": 29, "jti": "b9784a09a9f945cc83c52f571f2628cf", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNzEwMiwiaWF0IjoxNzA1MDMwNzAyLCJqdGkiOiJiOTc4NGEwOWE5Zjk0NWNjODNjNTJmNTcxZjI2MjhjZiIsInVzZXJfaWQiOjI5fQ.BeCIlpcXryFNZe04Hl0EQrkJAwkqcewEP4wiIzz7bwk", "created_at": "2024-01-12T03:38:22.070Z", "expires_at": "2024-01-13T03:38:22Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 67, "fields": {"user": 28, "jti": "9e85833ba0064daf845b47e79ab76d3a", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNzI2OSwiaWF0IjoxNzA1MDMwODY5LCJqdGkiOiI5ZTg1ODMzYmEwMDY0ZGFmODQ1YjQ3ZTc5YWI3NmQzYSIsInVzZXJfaWQiOjI4fQ.F3FJ8p1WTf7pX0TrV5XxL7i1GxOemm3UH6R_5yITwrg", "created_at": "2024-01-12T03:41:09.534Z", "expires_at": "2024-01-13T03:41:09Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 68, "fields": {"user": 28, "jti": "4af041a9b99c473aad1fdf90bf277fde", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNzQ3NSwiaWF0IjoxNzA1MDMxMDc1LCJqdGkiOiI0YWYwNDFhOWI5OWM0NzNhYWQxZmRmOTBiZjI3N2ZkZSIsInVzZXJfaWQiOjI4fQ.7kHsesr7MUJ13faJ-Y8UFaBnHebMs2Igff_x8OHxM_8", "created_at": "2024-01-12T03:44:35.011Z", "expires_at": "2024-01-13T03:44:35Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 69, "fields": {"user": 28, "jti": "8fee00b8241d4ebea19c0ecf17aac03d", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExNzU5MCwiaWF0IjoxNzA1MDMxMTkwLCJqdGkiOiI4ZmVlMDBiODI0MWQ0ZWJlYTE5YzBlY2YxN2FhYzAzZCIsInVzZXJfaWQiOjI4fQ.p8ZDa9cS4AfU-EM7ROocvPNyxXrLvJ6Aqx7NHKdDGaQ", "created_at": "2024-01-12T03:46:30.116Z", "expires_at": "2024-01-13T03:46:30Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 70, "fields": {"user": 28, "jti": "6528e81ad78f4cf3b9c4cd5099a70425", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExODA4MCwiaWF0IjoxNzA1MDMxNjgwLCJqdGkiOiI2NTI4ZTgxYWQ3OGY0Y2YzYjljNGNkNTA5OWE3MDQyNSIsInVzZXJfaWQiOjI4fQ.4OgnXUc2m8w6GzesS9kZYYZLaiHD4BYe0GOfcwQmhxg", "created_at": "2024-01-12T03:54:40.397Z", "expires_at": "2024-01-13T03:54:40Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 71, "fields": {"user": 29, "jti": "f8934b8b3bd146eea04f49a44af4e785", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExODM4MywiaWF0IjoxNzA1MDMxOTgzLCJqdGkiOiJmODkzNGI4YjNiZDE0NmVlYTA0ZjQ5YTQ0YWY0ZTc4NSIsInVzZXJfaWQiOjI5fQ.Prou-C84CLG5juf6aS3MsrkoJBtmMfrdeSqKg3Lny5w", "created_at": "2024-01-12T03:59:43.530Z", "expires_at": "2024-01-13T03:59:43Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 72, "fields": {"user": 28, "jti": "c004b5e7188646fc8a33cf76c668b922", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExODQ4OCwiaWF0IjoxNzA1MDMyMDg4LCJqdGkiOiJjMDA0YjVlNzE4ODY0NmZjOGEzM2NmNzZjNjY4YjkyMiIsInVzZXJfaWQiOjI4fQ.3Rcx8AEUXtasgFvexqFokc6jwzFZ1WVhAbxw6fSr4Og", "created_at": "2024-01-12T04:01:28.619Z", "expires_at": "2024-01-13T04:01:28Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 73, "fields": {"user": 29, "jti": "1778d32d47d14a698efc018002751f41", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExODk4NSwiaWF0IjoxNzA1MDMyNTg1LCJqdGkiOiIxNzc4ZDMyZDQ3ZDE0YTY5OGVmYzAxODAwMjc1MWY0MSIsInVzZXJfaWQiOjI5fQ.q4kUrm-GxNu8keVUs_pMqOSef336kz9pN0ctOXMAbxk", "created_at": "2024-01-12T04:09:45.083Z", "expires_at": "2024-01-13T04:09:45Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 74, "fields": {"user": 28, "jti": "771248bda14a487fbe2fe44705e81797", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTExOTU4MiwiaWF0IjoxNzA1MDMzMTgyLCJqdGkiOiI3NzEyNDhiZGExNGE0ODdmYmUyZmU0NDcwNWU4MTc5NyIsInVzZXJfaWQiOjI4fQ.Qt3xXHbf2eQphUf5UjDqo85MC2sihsy8ZosBI892rv8", "created_at": "2024-01-12T04:19:42.856Z", "expires_at": "2024-01-13T04:19:42Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 75, "fields": {"user": 29, "jti": "e39f0feaa17841f7bb930aebc1680cf8", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTEyOTA4MCwiaWF0IjoxNzA1MDQyNjgwLCJqdGkiOiJlMzlmMGZlYWExNzg0MWY3YmI5MzBhZWJjMTY4MGNmOCIsInVzZXJfaWQiOjI5fQ.QLpKiSryn6_vJXdoGvYDFztI1gOMfC2hi546iw2i4sI", "created_at": "2024-01-12T06:58:00.861Z", "expires_at": "2024-01-13T06:58:00Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 76, "fields": {"user": 28, "jti": "bbd2cadc94ee4b99a26d3a8aede30436", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTEzMzI0NSwiaWF0IjoxNzA1MDQ2ODQ1LCJqdGkiOiJiYmQyY2FkYzk0ZWU0Yjk5YTI2ZDNhOGFlZGUzMDQzNiIsInVzZXJfaWQiOjI4fQ.p12WfQ-PhZLftZhuxxGKqiL-Ko8t7XdPn5DNh--msWY", "created_at": "2024-01-12T08:07:25.837Z", "expires_at": "2024-01-13T08:07:25Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 77, "fields": {"user": 28, "jti": "b7f224f7cd9142b4b6276d0d981bf795", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTEzMzU4NiwiaWF0IjoxNzA1MDQ3MTg2LCJqdGkiOiJiN2YyMjRmN2NkOTE0MmI0YjYyNzZkMGQ5ODFiZjc5NSIsInVzZXJfaWQiOjI4fQ.4aeMY4loDEEs0A9_hhXKWPaWf7sjSBrFJ2luGpHaDfw", "created_at": "2024-01-12T08:13:06.518Z", "expires_at": "2024-01-13T08:13:06Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 78, "fields": {"user": 28, "jti": "2ee01eed854f46d29bc251417da979b7", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTE0MDE2MSwiaWF0IjoxNzA1MDUzNzYxLCJqdGkiOiIyZWUwMWVlZDg1NGY0NmQyOWJjMjUxNDE3ZGE5NzliNyIsInVzZXJfaWQiOjI4fQ.YNStb-NWQ_XlkGn9xZGX1Pz5UcsBfbH_Y9ato2Qwk90", "created_at": "2024-01-12T10:02:41.448Z", "expires_at": "2024-01-13T10:02:41Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 79, "fields": {"user": 28, "jti": "74bd723cf4df4c029e83030c1312d4d2", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTE0MTk4OCwiaWF0IjoxNzA1MDU1NTg4LCJqdGkiOiI3NGJkNzIzY2Y0ZGY0YzAyOWU4MzAzMGMxMzEyZDRkMiIsInVzZXJfaWQiOjI4fQ.r7LCPnGbmBqpNRIw3CmqbvGwZD-U77fzCgpzu8xAcB8", "created_at": "2024-01-12T10:33:08.423Z", "expires_at": "2024-01-13T10:33:08Z"}}, {"model": "token_blacklist.outstandingtoken", "pk": 80, "fields": {"user": 29, "jti": "d7f9467c8cfe4d1896783db96ff05e4f", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwNTE0MzEyMCwiaWF0IjoxNzA1MDU2NzIwLCJqdGkiOiJkN2Y5NDY3YzhjZmU0ZDE4OTY3ODNkYjk2ZmYwNWU0ZiIsInVzZXJfaWQiOjI5fQ.uhVaTeA9T2AcES_auqou4tNwWmprUwhIRw9cu3ojjTU", "created_at": "2024-01-12T10:52:00.766Z", "expires_at": "2024-01-13T10:52:00Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 1, "fields": {"token": 1, "blacklisted_at": "2024-01-04T08:30:12.977Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 2, "fields": {"token": 9, "blacklisted_at": "2024-01-05T02:15:26.756Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 3, "fields": {"token": 13, "blacklisted_at": "2024-01-05T02:27:07.233Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 4, "fields": {"token": 15, "blacklisted_at": "2024-01-05T02:32:36.211Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 5, "fields": {"token": 16, "blacklisted_at": "2024-01-05T04:15:27.871Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 6, "fields": {"token": 19, "blacklisted_at": "2024-01-05T04:16:41.497Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 7, "fields": {"token": 35, "blacklisted_at": "2024-01-05T11:52:25.322Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 8, "fields": {"token": 36, "blacklisted_at": "2024-01-08T02:34:26.343Z"}}, {"model": "token_blacklist.blacklistedtoken", "pk": 9, "fields": {"token": 39, "blacklisted_at": "2024-01-08T02:54:53.970Z"}}]
\ No newline at end of file
No preview for this file type
......@@ -10,6 +10,7 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from datetime import timedelta
import os
from pathlib import Path
......@@ -26,7 +27,7 @@ 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 = []
ALLOWED_HOSTS = ['10.0.2.2', '127.0.0.1']
# Application definition
......@@ -41,6 +42,11 @@ INSTALLED_APPS = [
'library',
'api',
'rest_framework',
'rest_framework.authtoken',
'phonenumber_field',
'rest_framework_simplejwt',
'rest_framework_simplejwt.token_blacklist',
'corsheaders',
]
MIDDLEWARE = [
......@@ -51,6 +57,8 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'library.middleware.UserTypeMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
ROOT_URLCONF = 'djangoproj.urls'
......@@ -64,6 +72,7 @@ TEMPLATES = [
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
......@@ -120,9 +129,13 @@ USE_TZ = True
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
# STATICFILES_DIRS = [
# os.path.join(BASE_DIR, 'static')
# ]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
......@@ -134,5 +147,22 @@ LOGIN_URL='/login'
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 5
'PAGE_SIZE': 10,
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
}
AUTH_USER_MODEL = 'library.CustomUser'
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(days=1),
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
}
\ No newline at end of file
......@@ -16,9 +16,14 @@ Including another URLconf
"""
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("library.urls")),
path('api/', include('api.urls')),
path('api-auth/', include('api.urls')),
]
from django.contrib import admin
from .models import Book, Member, BookLoan, Librarian, LoginHistory
from .models import Book, Member, BookLoan, Librarian, LoginHistory, CustomUser
# class PustakawanAdmin(admin.ModelAdmin):
# list_display = ('user',)
admin.site.register(Book)
admin.site.register(Member)
admin.site.register(BookLoan)
admin.site.register(Librarian)
admin.site.register(LoginHistory)
admin.site.register(CustomUser)
\ No newline at end of file
from functools import wraps
from django.shortcuts import redirect
def librarian_required(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Gantilah dengan mekanisme otentikasi sesuai kebutuhan Anda
if request.user.is_authenticated and request.user.is_librarian == True:
return view_func(request, *args, **kwargs)
else:
return redirect('unauthorized')
return _wrapped_view
\ No newline at end of file
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
from .models import *
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm
from django.contrib.auth.models import AbstractUser
from phonenumber_field.formfields import PhoneNumberField
from phonenumber_field.widgets import PhoneNumberPrefixWidget
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
class CustomAuthenticationForm(AuthenticationForm):
class Meta:
model = CustomUser
fields = ['username', 'password']
# def clean(self):
# cleaned_data = super().clean()
# password1 = cleaned_data.get('password1')
# password2 = cleaned_data.get('password2')
class LibrarianRegistrationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = UserCreationForm.Meta.fields + ('email', 'is_librarian',)
# if password1 and password2 and password1 != password2:
# raise forms.ValidationError('Passwords do not match')
class MemberRegistrationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = UserCreationForm.Meta.fields + ('email',)
# return cleaned_data
# class UserCreationForm(UserCreationForm):
# class Meta:
# model = User
# fields = UserCreationForm.Meta.fields + 'email'
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__'
class userCreat(UserCreationForm):
class MemberForm(forms.ModelForm):
phone_number = PhoneNumberField(
widget=PhoneNumberPrefixWidget(attrs={'class': 'form-control'})
)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
model = Member
fields = '__all__'
class LibrarianForm(forms.ModelForm):
phone_number = PhoneNumberField(
widget=PhoneNumberPrefixWidget(attrs={'class': 'form-control'})
)
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)
fields = ['name', 'last_name', 'address', 'birth_place', 'date_birth', 'phone_number']
class MemberProfileUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'name']
model = Member
fields = ['name', 'email', 'address', 'birth_place', 'date_birth', 'phone_number']
class BookForm(forms.ModelForm):
class LibrarianProfileUpdateForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'publisher', 'isbn']
model = Librarian
fields = ['name', 'last_name', 'address', 'birth_place', 'date_birth', 'phone_number']
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')
......
# middleware.py
from django.utils.functional import SimpleLazyObject
from .models import CustomUser # Gantilah dengan model pengguna yang sesuai
def get_user_type(request):
if hasattr(request, '_cached_user_type'):
return request._cached_user_type
user_type = 'member' # Default ke anggota
if request.user.is_authenticated:
user_type = 'librarian' if request.user.is_librarian else 'member'
request._cached_user_type = user_type
return user_type
class UserTypeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.user_type = SimpleLazyObject(lambda: get_user_type(request))
response = self.get_response(request)
return response
# Generated by Django 4.2.8 on 2023-12-19 07:31
# Generated by Django 4.2.8 on 2024-01-03 03:31
from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
......@@ -9,9 +14,36 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='Book',
fields=[
......@@ -19,17 +51,15 @@ class Migration(migrations.Migration):
('title', models.CharField(max_length=100)),
('author', models.CharField(max_length=100)),
('publisher', models.CharField(max_length=100)),
('date_publish', models.IntegerField(null=True)),
('isbn', models.CharField(max_length=13, unique=True)),
],
),
migrations.CreateModel(
name='Librarian',
name='Category',
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)),
('name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
......@@ -39,16 +69,30 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=100)),
('address', models.TextField()),
('email', models.EmailField(max_length=254, unique=True)),
('phone_number', models.CharField(max_length=15)),
('birth_place', models.CharField(max_length=50, null=True)),
('date_birth', models.DateField(null=True)),
('phone_number', models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')])),
('user', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
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')),
('login_time', models.DateTimeField(default=django.utils.timezone.now)),
('librarian', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
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)),
('address', models.TextField(null=True)),
('last_name', models.CharField(max_length=100, null=True)),
('birth_place', models.CharField(max_length=50, null=True)),
('date_birth', models.DateField(null=True)),
('user', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
......@@ -63,4 +107,9 @@ class Migration(migrations.Migration):
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.member')),
],
),
migrations.AddField(
model_name='book',
name='category',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.category'),
),
]
# Generated by Django 4.2.8 on 2024-01-03 07:03
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='librarian',
name='phone_number',
field=models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]),
),
]
# 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-22 06:08
# Generated by Django 4.2.8 on 2024-01-03 08:08
from django.db import migrations, models
......@@ -6,18 +6,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0003_remove_loginhistory_logout_time_and_more'),
('library', '0002_librarian_phone_number'),
]
operations = [
migrations.AddField(
model_name='bookloan',
name='is_late',
model_name='customuser',
name='is_librarian',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='bookloan',
name='late_fee',
field=models.IntegerField(default=0),
model_name='customuser',
name='is_member',
field=models.BooleanField(default=False),
),
]
# 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-28 06:52
# Generated by Django 4.2.8 on 2024-01-04 06:40
from django.db import migrations, models
......@@ -6,13 +6,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0008_book_category'),
('library', '0003_customuser_is_librarian_customuser_is_member'),
]
operations = [
migrations.AddField(
model_name='book',
name='date_publish',
field=models.DateField(null=True),
name='image',
field=models.ImageField(blank=True, null=True, upload_to='book_images/'),
),
]
# Generated by Django 4.2.8 on 2023-12-28 03:23
# Generated by Django 4.2.8 on 2024-01-04 06:41
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('library', '0007_category'),
('library', '0004_book_image'),
]
operations = [
migrations.AddField(
migrations.AlterField(
model_name='book',
name='category',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='library.category'),
preserve_default=False,
name='image',
field=models.ImageField(null=True, upload_to='book_images/'),
),
]
# 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 2024-01-08 06:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0005_alter_book_image'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='is_member',
field=models.BooleanField(default=True),
),
]
# 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)),
],
),
]
from django.shortcuts import redirect
class LibrarianRequiredMixin:
def dispatch(self, request, *args, **kwargs):
# Gantilah dengan mekanisme otentikasi sesuai kebutuhan Anda
if request.user.is_authenticated and request.user.is_librarian == True:
return super().dispatch(request, *args, **kwargs)
else:
return redirect('unauthorized')
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser, Group, Permission
from django.utils import timezone
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
import phonenumbers
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from phonenumbers import PhoneNumberFormat
# Create your models here.
class CustomUser(AbstractUser):
is_member = models.BooleanField(default=True)
is_librarian = models.BooleanField(default=False)
class Category(models.Model):
name = models.CharField(max_length=255)
......@@ -18,17 +25,39 @@ class Book(models.Model):
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)
date_publish = models.IntegerField(null=True)
image = models.ImageField(upload_to='book_images/', null=True)
isbn = models.CharField(max_length=13, unique=True)
def is_available(self):
return not self.bookloan_set.filter(is_returned=False).exists()
def __str__(self):
return self.title
class Member(models.Model):
user = models.OneToOneField(CustomUser, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
address = models.TextField()
email = models.EmailField(unique=True)
phone_number = models.CharField(max_length=15)
birth_place = models.CharField(max_length=50, null=True)
date_birth = models.DateField(null=True)
phone_regex = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
)
phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=True)
def clean(self):
super().clean()
try:
parsed_number = phonenumbers.parse(self.phone_number, None)
if not phonenumbers.is_valid_number(parsed_number):
raise ValidationError("Invalid phone number.")
self.phone_number = phonenumbers.format_number(parsed_number, PhoneNumberFormat.E164)
except phonenumbers.NumberParseException:
raise ValidationError("Error parsing phone number.")
def __str__(self):
return self.name
......@@ -45,18 +74,48 @@ class BookLoan(models.Model):
return f"{self.book.title} - {self.member.name}"
class Librarian(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
user = models.OneToOneField(CustomUser, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
address = models.TextField(null=True)
last_name = models.CharField(max_length=100, null=True)
birth_place = models.CharField(max_length=50, null=True)
date_birth = models.DateField(null=True)
phone_regex = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
)
phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=True)
def clean(self):
super().clean()
try:
parsed_number = phonenumbers.parse(self.phone_number, None)
if not phonenumbers.is_valid_number(parsed_number):
raise ValidationError("Invalid phone number.")
self.phone_number = phonenumbers.format_number(parsed_number, PhoneNumberFormat.E164)
except phonenumbers.NumberParseException:
raise ValidationError("Error parsing phone number.")
def __str__(self):
return self.name
@receiver(user_logged_in, sender=User)
@receiver(user_logged_in, sender=CustomUser)
def create_librarian_login_history(sender, user, **kwargs):
LoginHistory.objects.create(librarian=user)
# Setup librarian group and permissions
librarian_group, created = Group.objects.get_or_create(name='Librarian')
if created:
librarian_group.permissions.add(
Permission.objects.get(codename='add_book'),
Permission.objects.get(codename='change_book'),
Permission.objects.get(codename='delete_book'),
# Tambahkan izin lainnya sesuai kebutuhan
)
class LoginHistory(models.Model):
librarian = models.ForeignKey(User, on_delete=models.CASCADE)
librarian = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
login_time = models.DateTimeField(default=timezone.now)
def __str__(self):
......
......@@ -30,6 +30,14 @@
<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>
{% if request.user.is_member %}
<a class="dropdown-item" href="{% url 'update-usermember' %}">Edit</a>
{% else %}
<a class="dropdown-item" href="{% url 'update-userlibrarian' %}">Edit</a>
</li>
{% endif %}
<li><a class="dropdown-item" href="{% url 'update-password' %}">Change Password</a></li>
<li><a class="dropdown-item" href="{% url 'logout' %}">Logout</a></li>
</ul>
{% endif %}
......@@ -47,34 +55,49 @@
<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">
<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
Book
</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>
{% if request.user.is_librarian %}
<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
Member
</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
Book Loan
</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
Librarian
</a>
<a class="nav-link" href="{% url 'category_list' %}" aria-expanded="false">
<a class="nav-link" href="{% url 'near_outstanding_loans' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Category
Outstanding Book Loan
</a>
<a class="nav-link" href="{% url 'overdue_loans' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-book-open"></i></div>
Overdue Book Loan
</a>
{% endif%}
{%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">
<a class="nav-link" href="{% url 'member_registration' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-columns"></i></div>
Register Member
</a>
<a class="nav-link" href="{% url 'librarian_registration' %}" aria-expanded="false">
<div class="sb-nav-link-icon"><i class="fas fa-columns"></i></div>
register
Register Librarian
</a>
{% endif %}
</div>
......
{% extends 'base.html' %}
{% block content %}
<h1>Confirm Delete</h1>
<p>Are you sure you want to delete "{{ book.title }}"?</p>
<form method="post">
{% csrf_token %}
<button type="submit">Delete</button>
<a href="{% url 'book-list' %}">Cancel</a>
</form>
{% endblock %}
\ 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">Detail Book</div>
<div class="card-body">
<form>
<div class="mb-3">
<label for="id_title" class="form-label">Book Title</label>
<input readonly type="text" name="title" id="id_title" value="{{ book.title }}" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_category">Category:</label>
<input readonly type="text" name="category" id="id_title" value="{{ book.category.name }}" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_author" class="form-label">Author</label>
<input readonly type="text" name="author" id="id_author" value="{{ book.author }}" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_publisher" class="form-label">Publisher</label>
<input readonly type="text" name="publisher" id="id_publisher" value="{{ book.publisher }}" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_publish">Date Publish:</label>
<input readonly type="number" name="date_publish" id="id_date_publish" value="{{ book.date_publish }}" class="form-control" required>
</div>
<div class="mb-3">
<p>Image</p>
<img src="{{ book.image.url }}" width="200px" height="150px" alt="">
</div>
<div class="mb-3">
<label for="id_isbn" class="form-label">ISBN</label>
<input readonly type="text" name="isbn" id="id_isbn" value="{{ book.isbn }}" class="form-control" required>
</div>
<a class="btn btn-primary col-2 mx-2" href="{% url 'book-edit' book.pk %}"" role="button">Edit</a>
<a class="btn btn-danger col-2 mx-2" href="{% url 'book-delete' book.pk %}"" role="button">Delete</a>
<a class="btn btn-warning col-2 mx-2" href="{% url 'book-list' %}"" role="button">Back</a>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -11,32 +11,40 @@
<table id="datatablesSimple">
<thead >
<tr>
<th>Image</th>
<th>Title</th>
<th>Category</th>
<th>Author</th>
<th>Publisher</th>
<th>ISBN</th>
<th>Date Publish</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Image</th>
<th>Title</th>
<th>Category</th>
<th>Author</th>
<th>Publisher</th>
<th>ISBN</th>
<th>Date Publish</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
{% for book in books %}
<tr>
<td>
{% if book.image %}
<img src="{{ book.image.url }}" width="100px" height="70px" alt="">
{% endif %}
</td>
<td>{{ book.title }}</td>
<td>{{ book.category.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.isbn }}</td>
<td>{{ book.date_publish }}</td>
<td>
<a class="btn btn-success col-2 mx-2" href="detail/{{book.id}}" role="button">Detail</a>
<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>
<a class="btn btn-danger col-2 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 %}
......
......@@ -51,8 +51,6 @@
<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>
......
......@@ -9,17 +9,19 @@
<div class="card-body">
<form method="post" action="{% url 'book_loan_new' %}">
{% csrf_token %}
<div class="mb-3">
<div class="form-group mb-3">
<label for="id_book">Book:</label>
<select name="book" id="id_book" class="form-control" required>
<option selected>Select Book</option>
{% for book in books %}
<option value="{{ book.id }}">{{ book.title }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<div class="form-group mb-3">
<label for="id_member">Member:</label>
<select name="member" id="id_member" class="form-control" required>
<option selected>Select Member</option>
{% for member in members %}
<option value="{{ member.id }}">{{ member.name }}</option>
{% endfor %}
......@@ -30,6 +32,7 @@
<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>
<a class="btn btn-warning col-2 mx-2" href="{% url 'book_loan_list' %}" role="button">Back</a>
</form>
</div>
</div>
......
......@@ -42,7 +42,8 @@
<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>
<button type="submit" class="btn btn-primary col-1 mx-2">Save</button>
<a class="btn btn-warning col-1 mx-2" href="{% url 'book_loan_list' %}" role="button">Back</a>
</form>
</div>
......
......@@ -7,12 +7,20 @@
<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' %}">
<form method="post" action="{% url 'book-new' %}" enctype="multipart/form-data">
{% 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_category">Category:</label>
<select name="category" id="id_category" class="form-control" required>
{% for category in category %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
</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>
......@@ -21,11 +29,20 @@
<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_date_publish">Date Publish:</label>
<input type="number" name="date_publish" id="id_date_publish" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_image">Input Image</label>
<input type="file" name="image" id="id_image" 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>
<a class="btn btn-warning col-2 mx-2" href="{% url 'book-list' %}"" role="button">Back</a>
</form>
</div>
</div>
......@@ -34,12 +51,4 @@
</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
......@@ -7,11 +7,19 @@
<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 %}">
<form method="post" action="{% url 'book-edit' pk=book.pk %}" enctype="multipart/form-data">
{% 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>
<input readonly 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_category">Category:</label>
<select name="category" id="id_category" class="form-control" required>
{% for category in category %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="id_author" class="form-label">Author</label>
......@@ -21,11 +29,20 @@
<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_date_publish">Date Publish:</label>
<input type="number" name="date_publish" id="id_date_publish" value="{{ book.date_publish }}" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_image">Input Image</label>
<input type="file" name="image" id="id_image" value="{{ book.image }}"" 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>
<a class="btn btn-danger col-2 mx-2" href="{% url 'book-list' %}" role="button">Back</a>
</form>
</div>
</div>
......
......@@ -12,11 +12,13 @@
<thead >
<tr>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
......@@ -24,19 +26,28 @@
<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>
<a class="btn btn-secondary col-1 mx-3" href="{% url 'category_edit' pk=category.pk %}" role="button">Edit</a>
<a class="btn btn-danger col-1 mx-3" href="delete/{{category.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 '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>
<a class="btn btn-primary col-1 mx-3" href="{% url 'category_new' %}" role="button">Add Category</a>
</div>
</div>
</div>
</div>
{% endblock content%}
<!-- <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> -->
<!-- <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> -->
\ 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 'librarian_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">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card">
<div class="card-header bg-primary text-white">Member Registration</div>
<div class="card-body">
<form method="post" action="{% url 'librarian_registration' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group m-3">
<label for="">Username</label>
{{ form.username }}
</div>
<div class="form-group m-3">
<label for="">Email</label>
{{ form.email }}
</div>
<div class="form-group m-3">
<label for="">Is Librarian:</label>
{{ form.is_librarian }}
</div>
<div class="form-group m-2">
<label for="">Password</label>
{{ form.password1 }}
</div>
<div class="form-group m-2">
<label for="">Confirm Password</label>
{{ form.password2 }}
</div>
<button type="submit" class="btn btn-primary" role="button">Create</button>
<a class="btn btn-danger col-2 mx-2" href="{% url 'book-list' %}" role="button">Back</a>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Create Account</h2>
<form method="post" action="{% url 'librarian_registration' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
......@@ -7,7 +7,7 @@
<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 %}">
<form method="POST" action="{% url 'librarian_edit' id=librarian.id %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_name">Name:</label>
......@@ -15,24 +15,33 @@
</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>
<label for="id_lastname">Last Name:</label>
<input type="text" name="last_name" id="id_lastname" value="{{ librarian.last_name }}" placeholder="Last Name" 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>
<label for="id_address">Address:</label>
<textarea type="text" name="address" id="id_address" value="{{ librarian.address }}" placeholder="Address" class="form-control" required></textarea>
</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>
<label for="id_birthplace">Birth Place:</label>
<input type="text" name="birth_place" id="id_lastname" value="{{ librarian.birth_place }}" placeholder="Birth Place" 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>
<label for="id_datebirth">Birth date:</label>
<input type="date" name="date_birth" id="id_datebirth" value="{{ librarian.date_birth }}" placeholder="Birth Date" 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="{{ librarian.phone_number }}" placeholder="Phone Number" class="form-control" required> -->
{{form.phone_number}}
</div>
<button type="submit" class="btn btn-primary" role="button">Save Changes</button>
</form>
</div>
......@@ -41,38 +50,15 @@
</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 %}">
<h2>Edit</h2>
<form method="post" action="{% url 'librarian_edit' id=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>
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
{% endblock content%}
\ No newline at end of file
......@@ -19,6 +19,8 @@
<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>
<input type="checkbox" onclick="showPassword()"> Show Password
<br>
</div>
<button type="submit" class="btn btn-primary" role="button">Login</button>
</form>
......@@ -29,5 +31,17 @@
</div>
</div>
<script>
function showPassword() {
var passwordInput = document.getElementById('id_password');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
} else {
passwordInput.type = 'password';
}
}
</script>
{% endblock content%}
......@@ -36,7 +36,7 @@
<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>
<a class="btn btn-danger col-3 mx-3" href="delete/{{member.id}}" role="button" onclick="return confirm('Are you sure you want to delete {{ member.name }}')">Delete</a>
</td>
</tr>
{% endfor %}
......
{% 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 'member_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%}
......@@ -19,13 +19,22 @@
</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>
<textarea type="text" name="address" id="id_address" placeholder="Input Address" class="form-control" required></textarea>
</div>
<div class="mb-3">
<label for="id_birth_place" class="form-label">Birth Place</label>
<input type="text" name="birth_place" id="id_birth_place" placeholder="Input Birth Place" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_birth" class="form-label">Birth Date</label>
<input type="date" name="date_birth" id="id_date_birth" placeholder="Input datebirth" 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>
{{form.phone_number}}
</div>
<button type="submit" class="btn btn-primary" role="button">Add</button>
<a class="btn btn-warning col-2 mx-2" href="{% url 'member_list' %}"" role="button">Back</a>
</form>
</div>
</div>
......
{% extends 'base.html' %}
{% block content%}
<!-- <div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5">
<div class="card p-4">
<h2>Create Account</h2>
<form method="post" action="{% url 'member_registration' %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div> -->
<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">Member Registration</div>
<div class="card-body">
<form method="post" action="{% url 'member_registration' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group m-3">
<label for="">Username</label>
{{ form.username }}
</div>
<div class="form-group m-3">
<label for="">Email</label>
{{ form.email }}
</div>
<div class="form-group m-3">
<label for="">Is Member:</label>
{{ form.is_member }}
</div>
<div class="form-group m-2">
<label for="">Password</label>
{{ form.password1 }}
<!-- <input type="checkbox" onclick="showPassword()"> Show Password
<br> -->
</div>
<div class="form-group m-2">
<label for="">Confirm Password</label>
{{ form.password2 }}
<!-- <input type="checkbox" onclick="showPassword()"> Show Password
<br> -->
</div>
<button type="submit" class="btn btn-primary" role="button">Create</button>
<a class="btn btn-danger col-2 mx-2" href="{% url 'book-list' %}" role="button">Back</a>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <script>
function showPassword() {
var passwordInput = document.getElementById('id_password');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
} else {
passwordInput.type = 'password';
}
}
</script> -->
{% endblock content%}
\ No newline at end of file
......@@ -19,13 +19,22 @@
</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>
<textarea type="text" name="address" id="id_address" value="{{ member.address }}" placeholder="Input Address" class="form-control" required></textarea>
</div>
<div class="mb-3">
<label for="id_birth_place" class="form-label">Birth Place</label>
<input type="text" name="birth_place" id="id_birth_place" value="{{ member.birth_place }}" placeholder="Input Birth Place" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_birth" class="form-label">Birth Date</label>
<input type="date" name="date_birth" id="id_date_birth" value="{{ member.date_birth }}" placeholder="Input datebirth" 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>
<a class="btn btn-warning col-2 mx-2" href="{% url 'member_list' %}"" role="button">Back</a>
</form>
</div>
</div>
......
......@@ -15,7 +15,6 @@
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Overdue Date</th>
</tr>
</thead>
......@@ -25,7 +24,6 @@
<th>Member Name</th>
<th>Loan Date</th>
<th>Due Date</th>
<th>Return Date</th>
<th>Overdue Date</th>
</tr>
</tfoot>
......@@ -36,8 +34,7 @@
<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>
<td>{{ loan.dead}}</td>
</tr>
{% endfor %}
</tbody>
......
......@@ -10,8 +10,12 @@
<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>
<label for="id_name" class="form-label">First Name</label>
<input type="text" name="name" id="id_name" placeholder="First Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_lname" class="form-label">Last Name</label>
<input type="text" name="lname" id="id_lname" placeholder="Last Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_username" class="form-label">Username</label>
......@@ -21,6 +25,18 @@
<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_address" class="form-label">Address</label>
<textarea type="text" name="address" id="id_address" placeholder="Input Address" class="form-control" required></textarea>
</div>
<div class="mb-3">
<label for="id_birth_place" class="form-label">Birth Place</label>
<input type="text" name="birth_place" id="id_birth_place" placeholder="Input Birth Place" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_birth" class="form-label">Birth Date</label>
<input type="date" name="date_birth" id="id_date_birth" placeholder="Input datebirth" 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>
......@@ -38,14 +54,13 @@
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<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 }}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div> -->
</div>
{% endblock content%}
{% extends 'base.html' %}
{% block content%}
<div class="container-fluid px-4 pt-3">
<h2 style="text-align: center;" font-family: serif;>You dont have Permissions!</h2>
</div>
{% load static %}
<img src="{% static 'assets/perpustakaan.jpg' %}" class="img-fluid" alt="Perpustakaan">
{% endblock %}
{% 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">Change Password</div>
<div class="card-body">
<form method="post" action="{% url 'update-password' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_old_password" class="form-label">Current Password</label>
<input type="password" name="old_password" id="id_old_password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_new_password" class="form-label">New Password</label>
<input type="password" name="new_password" id="id_new_password" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_confirm_password" class="form-label">Confirm Password</label>
<input type="password" name="confirm_password" id="id_confirm_password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Change Password</button>
<a class="btn btn-danger col-2 mx-2" href="{% url 'dashboard' %}"" role="button">Back</a>
</form>
</div>
</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">Edit Profile</div>
<div class="card-body">
<form method="post" action="{% url 'update-userlibrarian' %}">
{% 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_last_name" class="form-label">Last Name</label>
<input type="text" name="last_name" id="id_last_name" placeholder="Input Last Name" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_address" class="form-label">Address</label>
<textarea type="text" name="address" id="id_address" placeholder="Input Address" class="form-control" required></textarea>
</div>
<div class="mb-3">
<label for="id_birth_place" class="form-label">Birth Place</label>
<input type="text" name="birth_place" id="id_birth_place" placeholder="Input Birth Place" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_birth" class="form-label">Birth Date</label>
<input type="date" name="date_birth" id="id_date_birth" placeholder="Input datebirth" 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="{{ librarian.phone_number }}" placeholder="Phone Number" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary" role="button">Save</button>
<a class="btn btn-danger col-2 mx-2" href="{% url 'dashboard' %}"" role="button">Back</a>
</form>
</div>
</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">Edit Profile</div>
<div class="card-body">
<form method="post" action="{% url 'update-usermember' %}">
{% 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" placeholder="Input Email" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_address" class="form-label">Address</label>
<textarea type="text" name="address" id="id_address" placeholder="Input Address" class="form-control" required></textarea>
</div>
<div class="mb-3">
<label for="id_birth_place" class="form-label">Birth Place</label>
<input type="text" name="birth_place" id="id_birth_place" placeholder="Input Birth Place" class="form-control" required>
</div>
<div class="mb-3">
<label for="id_date_birth" class="form-label">Birth Date</label>
<input type="date" name="date_birth" id="id_date_birth" placeholder="Input datebirth" 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</button>
<a class="btn btn-danger col-2 mx-2" href="{% url 'dashboard' %}"" role="button">Back</a>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div style="text-align: center; margin-top: 50px;">
<h2>Update Profile</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;>Your Password Has Been Change!</h2>
</div>
{% load static %}
<img src="{% static 'assets/perpustakaan.jpg' %}" class="img-fluid" alt="Perpustakaan">
{% endblock %}
\ 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;>Your Profile Has Been Update!</h2>
</div>
{% load static %}
<img src="{% static 'assets/perpustakaan.jpg' %}" class="img-fluid" alt="Perpustakaan">
{% endblock %}
\ No newline at end of file
from django.urls import path
from django.contrib.auth.views import LogoutView
from django.contrib.auth.views import LogoutView, LoginView
from .views import *
from django.views.generic import TemplateView, ListView
from django.views.generic import *
from django.conf.urls.static import static
urlpatterns = [
path('', homepage, name='homepage'),
path('login/', login_view, name='login'),
# path('login/', login_view, name='login'),
# path('register/', register, name='register'),
path('login/', Login, name='login'),
path('logout/', LogoutView.as_view(next_page='homepage'), name='logout'),
path('register/', register_view, name='register'),
path('dashboard/', dashboard, name='dashboard'),
path('librarian-registration/', librarian_registration, name='librarian_registration'),
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/edit/<int:id>/', 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/', BookList.as_view(), name='book-list'),
path('books/detail/<int:pk>/', BookDetail.as_view(), name='book-detail'),
path('books/add/', BookCreateView.as_view(), name='book-new'),
path('books/edit/<int:pk>/', BookUpdateView.as_view(), name='book-edit'),
path('books/delete/<int:id>/', book_delete, name='delete_book'),
path('books/<int:pk>/delete/', BookDeleteView.as_view(), name='book-delete'),
path('book-loans/', book_loan_list, name='book_loan_list'),
path('book-loans/add/', book_loan_new, name='book_loan_new'),
......@@ -27,9 +32,13 @@ urlpatterns = [
# 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('bookloans/', BookLoanList.as_view(), name='bookloan-list'),
path('near-outstanding-loans/', near_outstanding_loans, name='near_outstanding_loans'),
path('overdue-loans/', overdue_loans, name='overdue_loans'),
path('member-registration/', member_registration, name='member_registration'),
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'),
......@@ -37,9 +46,20 @@ urlpatterns = [
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('update-usermember/', update_usermember, name='update-usermember'),
path('update-userlibrarian/', update_userlibrarian, name='update-userlibrarian'),
path('updateuser_success/', updateuser_success, name='updateuser_success'),
path('update-password', userchange_password, name='update-password'),
path('updatepassword_success/', updateuser_success, name='updatepassword_success'),
path('categories/', CategoryListView.as_view(), name='category_list'),
path('category/add/', CategoryCreateView.as_view(), name='category_new'),
path('category/edit/<int:pk>/', CategoryUpdateView.as_view(), name='category_edit'),
path('unauthorized/', unauthorized, name='unauthorized'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
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