From ea8ffb9a7a0ca670c62022d9e1d72f4dbbdb0ea9 Mon Sep 17 00:00:00 2001
From: ankur12-1610 <76884959+ankur12-1610@users.noreply.github.com>
Date: Mon, 19 Jul 2021 16:56:51 +0530
Subject: [PATCH 1/6] Auth
---
authentication/templates/login.html | 12 +++++++
authentication/templates/register.html | 12 +++++++
authentication/urls.py | 8 +++++
authentication/views.py | 46 +++++++++++++++++++++++---
library/forms.py | 17 ++++++++++
library/urls.py | 2 ++
store/templates/store/base.html | 5 +--
store/views.py | 28 ++++++++++++++--
8 files changed, 120 insertions(+), 10 deletions(-)
create mode 100644 authentication/templates/login.html
create mode 100644 authentication/templates/register.html
create mode 100644 library/forms.py
diff --git a/authentication/templates/login.html b/authentication/templates/login.html
new file mode 100644
index 0000000..f1006cc
--- /dev/null
+++ b/authentication/templates/login.html
@@ -0,0 +1,12 @@
+{% extends "store/base.html" %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/authentication/templates/register.html b/authentication/templates/register.html
new file mode 100644
index 0000000..673e7a6
--- /dev/null
+++ b/authentication/templates/register.html
@@ -0,0 +1,12 @@
+{% extends "store/base.html" %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/authentication/urls.py b/authentication/urls.py
index e69de29..9460265 100644
--- a/authentication/urls.py
+++ b/authentication/urls.py
@@ -0,0 +1,8 @@
+from django.urls import path
+from authentication.views import *
+
+urlpatterns = [
+ path("login/", loginView, name="loginView"),
+ path("register/", registerView, name="register"),
+ path("logout/", logoutView, name="logout"),
+]
\ No newline at end of file
diff --git a/authentication/views.py b/authentication/views.py
index 14dd530..d597b8c 100644
--- a/authentication/views.py
+++ b/authentication/views.py
@@ -1,13 +1,49 @@
-from django.shortcuts import render
-from django.contrib.auth import login,logout,authenticate
+from django.shortcuts import render, redirect
+from django.http import HttpResponse
+from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
+from django.contrib.auth import login,logout,authenticate
+from django.contrib import messages
+from library.forms import NewUserForm
# Create your views here.
def loginView(request):
- pass
+ if request.method == "POST":
+ form = AuthenticationForm(request, data=request.POST)
+ if form.is_valid():
+ username = form.cleaned_data.get('username')
+ password = form.cleaned_data.get('password')
+ user = authenticate(username=username, password=password)
+ if user is not None:
+ login(request, user)
+ messages.info(request, f"You are now logged in as {username}")
+ return redirect("index")
+ else:
+ messages.error(request, "Invalid username or password.")
+ else:
+ messages.error(request, "Invalid username or password.")
+ form = AuthenticationForm()
+ return render(request, 'login.html', {'form': form})
def logoutView(request):
- pass
+ logout(request)
+ messages.info(request, "Logged out successfully!")
+ return redirect("index")
def registerView(request):
- pass
\ No newline at end of file
+ if request.method == "POST":
+ form = NewUserForm(request.POST)
+ if form.is_valid():
+ user = form.save()
+ username = form.cleaned_data.get('username')
+ messages.success(request, f"New Account Created: {username}")
+ login(request, user)
+ messages.info(request, f"You are now logged in as {username}")
+ return redirect("index")
+
+ else:
+ for msg in form.error_messages:
+ messages.error(request, f"{msg}: {form.error_messages[msg]}")
+
+ form = NewUserForm
+ return render(request, 'register.html', {'form': form})
\ No newline at end of file
diff --git a/library/forms.py b/library/forms.py
new file mode 100644
index 0000000..1b3cbb8
--- /dev/null
+++ b/library/forms.py
@@ -0,0 +1,17 @@
+from django import forms
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+
+class NewUserForm(UserCreationForm):
+ email = forms.EmailField(required=True)
+
+ class Meta:
+ model = User
+ fields = ("username", "email", "password1", "password2")
+
+ def save(self, commit=True):
+ user = super(NewUserForm, self).save(commit=False)
+ user.email = self.cleaned_data['email']
+ if commit:
+ user.save()
+ return user
diff --git a/library/urls.py b/library/urls.py
index 60b7957..b078f8f 100644
--- a/library/urls.py
+++ b/library/urls.py
@@ -20,6 +20,8 @@
urlpatterns = [
path('',include('store.urls')),
+ path('', include('authentication.urls')),
path('admin/', admin.site.urls),
+ path('authentication/',include('django.contrib.auth.urls')),
path('accounts/',include('django.contrib.auth.urls')),
]+static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
diff --git a/store/templates/store/base.html b/store/templates/store/base.html
index 64b7a6e..f0b2238 100644
--- a/store/templates/store/base.html
+++ b/store/templates/store/base.html
@@ -26,10 +26,11 @@
diff --git a/store/views.py b/store/views.py
index dc411b9..3343a4a 100644
--- a/store/views.py
+++ b/store/views.py
@@ -17,7 +17,15 @@ def bookDetailView(request, bid):
'num_available': None, # set this to the number of copies of the book available, or 0 if the book isn't available
}
# START YOUR CODE HERE
-
+ book = get_object_or_404(Book, id=bid)
+ bookcopy = get_object_or_404(BookCopy, book=book)
+
+ context['book'] = book
+
+ if book.is_available:
+ context['num_available'] = len(bookcopy)
+ else:
+ context['num_available'] = 0
return render(request, template_name, context=context)
@@ -31,7 +39,9 @@ def bookListView(request):
}
get_data = request.GET
# START YOUR CODE HERE
-
+ var = Book.objects.filter(title__icontains=get_data.get('title',''), author__icontains=get_data.get('author',''), genre__icontains=get_data.get('genre',''))
+
+ context['books'] = var
return render(request, template_name, context=context)
@@ -46,8 +56,10 @@ def viewLoanedBooks(request):
BookCopy model. Only those book copies should be included which have been loaned by the user.
'''
# START YOUR CODE HERE
-
+ user = request.user
+ loanedBookCopy = BookCopy.objects.filter(borrower=user)
+ context['books'] = loanedBookCopy
return render(request, template_name, context=context)
@@ -62,6 +74,16 @@ def loanBookView(request):
If yes, then set the message to 'success', otherwise 'failure'
'''
# START YOUR CODE HERE
+ book = get_object_or_404(Book, id=request.POST.get('book_id'))
+ if book.is_available:
+ user = request.user
+ bookCopy = BookCopy.objects.get(book=book, borrower=None)
+ bookCopy.borrower = user
+ bookCopy.save()
+ response_data['message'] = 'success'
+ else:
+ response_data['message'] = 'failure'
+
book_id = None # get the book id from post data
From 63e8694c9b30c74001c0cb2413a46c44a8e8b580 Mon Sep 17 00:00:00 2001
From: ankur12-1610 <76884959+ankur12-1610@users.noreply.github.com>
Date: Wed, 21 Jul 2021 14:15:15 +0530
Subject: [PATCH 2/6] Return
---
store/migrations/0003_auto_20210720_1844.py | 35 +++++
store/models.py | 8 ++
store/templates/store/book_detail.html | 60 +++++++++
store/templates/store/loaned_books.html | 25 +++-
store/urls.py | 1 +
store/views.py | 135 ++++++++++++--------
6 files changed, 207 insertions(+), 57 deletions(-)
create mode 100644 store/migrations/0003_auto_20210720_1844.py
diff --git a/store/migrations/0003_auto_20210720_1844.py b/store/migrations/0003_auto_20210720_1844.py
new file mode 100644
index 0000000..a3d52a6
--- /dev/null
+++ b/store/migrations/0003_auto_20210720_1844.py
@@ -0,0 +1,35 @@
+# Generated by Django 2.2.1 on 2021-07-20 13:14
+
+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),
+ ('store', '0002_auto_20190607_1302'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='bookcopy',
+ name='borrow_date',
+ field=models.DateField(blank=True, null=True),
+ ),
+ migrations.AlterField(
+ model_name='bookcopy',
+ name='borrower',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='borrower', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.CreateModel(
+ name='UserRating',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('rating', models.FloatField(default=0)),
+ ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.Book')),
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='user', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/store/models.py b/store/models.py
index 17c63a3..c806825 100644
--- a/store/models.py
+++ b/store/models.py
@@ -30,3 +30,11 @@ def __str__(self):
else:
return f'{self.book.title} - Available'
+class BookRating(models.Model):
+ user=models.ForeignKey(User, related_name='user', null=True, blank=True, on_delete=models.SET_NULL)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ rating = models.FloatField(default=0.0)
+
+ def __str__(self):
+ return f'{self.book.title}'
+
diff --git a/store/templates/store/book_detail.html b/store/templates/store/book_detail.html
index 2e4b9e8..f4f77ce 100644
--- a/store/templates/store/book_detail.html
+++ b/store/templates/store/book_detail.html
@@ -20,6 +20,37 @@ Title: {{ book.title }}
Rs. {{ book.mrp }}
Available Copies:
{{ num_available }}
+ {% if user.is_authenticated %}
+
+ Rate:
+
+
+
+ {% csrf_token %}
+
+
+
+
+
+
+
+
+
+
+ {% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/store/templates/store/loaned_books.html b/store/templates/store/loaned_books.html
index d6f2044..b329b79 100644
--- a/store/templates/store/loaned_books.html
+++ b/store/templates/store/loaned_books.html
@@ -37,7 +37,28 @@ Loaned Books list
{% endblock %}
\ No newline at end of file
diff --git a/store/urls.py b/store/urls.py
index 4520334..9857608 100644
--- a/store/urls.py
+++ b/store/urls.py
@@ -8,4 +8,5 @@
path('books/loaned/', viewLoanedBooks, name="view-loaned"),
path('books/loan/', loanBookView, name="loan-book"),
path('books/return/', returnBookView, name="return-book"),
+ path('book/bookrating/', rateBookView, name="rate-book" )
]
diff --git a/store/views.py b/store/views.py
index 3343a4a..a75c844 100644
--- a/store/views.py
+++ b/store/views.py
@@ -1,11 +1,12 @@
-from django.shortcuts import render
+from django.shortcuts import render,redirect
from django.shortcuts import get_object_or_404
+from django.shortcuts import get_list_or_404
+from datetime import date
from store.models import *
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
-# Create your views here.
def index(request):
return render(request, 'store/index.html')
@@ -13,36 +14,27 @@ def index(request):
def bookDetailView(request, bid):
template_name = 'store/book_detail.html'
context = {
- 'book': None, # set this to an instance of the required book
- 'num_available': None, # set this to the number of copies of the book available, or 0 if the book isn't available
- }
- # START YOUR CODE HERE
- book = get_object_or_404(Book, id=bid)
- bookcopy = get_object_or_404(BookCopy, book=book)
-
+ 'book': None,
+ 'num_available': None,
+ }
+ book = get_object_or_404(Book, pk=bid)
+ bookcopy = get_list_or_404(BookCopy, book=bid)
context['book'] = book
-
- if book.is_available:
- context['num_available'] = len(bookcopy)
- else:
- context['num_available'] = 0
-
- return render(request, template_name, context=context)
+ context['num_available'] = len(bookcopy)
+ return render(request, template_name, context)
@csrf_exempt
def bookListView(request):
template_name = 'store/book_list.html'
context = {
- 'books': None, # set this to the list of required books upon filtering using the GET parameters
- # (i.e. the book search feature will also be implemented in this view)
+ 'books': None,
}
get_data = request.GET
- # START YOUR CODE HERE
- var = Book.objects.filter(title__icontains=get_data.get('title',''), author__icontains=get_data.get('author',''), genre__icontains=get_data.get('genre',''))
+
+ var = Book.objects.filter(title__icontains=get_data.get('title',''),author__icontains=get_data.get('author',''),genre__icontains=get_data.get('genre', ''))
context['books'] = var
-
return render(request, template_name, context=context)
@login_required
@@ -51,16 +43,8 @@ def viewLoanedBooks(request):
context = {
'books': None,
}
- '''
- The above key 'books' in the context dictionary should contain a list of instances of the
- BookCopy model. Only those book copies should be included which have been loaned by the user.
- '''
- # START YOUR CODE HERE
- user = request.user
- loanedBookCopy = BookCopy.objects.filter(borrower=user)
-
- context['books'] = loanedBookCopy
-
+ loanedbookcopy = BookCopy.objects.filter(borrower=request.user)
+ context['books'] = loanedbookcopy
return render(request, template_name, context=context)
@csrf_exempt
@@ -69,36 +53,77 @@ def loanBookView(request):
response_data = {
'message': None,
}
- '''
- Check if an instance of the asked book is available.
- If yes, then set the message to 'success', otherwise 'failure'
- '''
- # START YOUR CODE HERE
- book = get_object_or_404(Book, id=request.POST.get('book_id'))
- if book.is_available:
- user = request.user
- bookCopy = BookCopy.objects.get(book=book, borrower=None)
- bookCopy.borrower = user
- bookCopy.save()
- response_data['message'] = 'success'
- else:
- response_data['message'] = 'failure'
-
- book_id = None # get the book id from post data
+ if request.method == 'POST':
+ bid = request.POST.get('bid', None)
+ bookcopy = BookCopy.objects.filter(book=bid, status=True)
+ if len(bookcopy) > 0:
+ bookcopy[0].borrower = request.user
+ bookcopy[0].borrower_date = date.today()
+ bookcopy[0].status = False
+ bookcopy[0].save()
+ response_data['message'] = 'success'
+ else:
+ response_data['message'] = 'not available'
+
return JsonResponse(response_data)
-'''
-FILL IN THE BELOW VIEW BY YOURSELF.
-This view will return the issued book.
-You need to accept the book id as argument from a post request.
-You additionally need to complete the returnBook function in the loaned_books.html file
-to make this feature complete
-'''
+
@csrf_exempt
@login_required
def returnBookView(request):
- pass
+ response_data = {
+ 'message': None,
+ }
+ if request.method == 'POST':
+ bid = request.POST.get('bid', None)
+ bookcopy = BookCopy.objects.filter(book=bid, status=True)
+ if len(bookcopy) > 0:
+ bookcopy[0].borrower = None
+ bookcopy[0].borrower_date = date.today()
+ bookcopy[0].status = True
+ bookcopy[0].save()
+ response_data['message'] = 'success'
+ else:
+ response_data['message'] = 'failiure'
+
+ return JsonResponse(response_data)
+
+@csrf_exempt
+@login_required
+def rateBookView(request):
+
+ if request.method == "POST":
+ data = request.POST
+ bid=data.get('bid','')
+ rate=data.get('rate',0.0)
+ print(bid)
+ print(rate)
+ book = Book.objects.get(pk=bid)
+ oldRating=BookRating.objects.filter(user=request.user,book=book)
+ rating=BookRating()
+ rating.book=book
+ rating.user=request.user
+ rating.rating=rate
+ oldRating.delete()
+ rating.save()
+ other=BookRating.objects.filter(book=book)
+ rating_sum = 0.0
+ for current in other:
+ rating_sum += current.rating
+ book.rating = rating_sum/other.count()
+ book.rating = round(book.rating,2)
+ book.save()
+ response_data={
+ 'message':'success'
+ }
+ else:
+ response_data={
+ 'message':'failure'
+ }
+
+
+ return JsonResponse(response_data)
From 89789da836ff32a0868ebbcfe7f1486a59eb6fc8 Mon Sep 17 00:00:00 2001
From: ankur12-1610 <76884959+ankur12-1610@users.noreply.github.com>
Date: Wed, 21 Jul 2021 15:21:45 +0530
Subject: [PATCH 3/6] Minor changes
---
authentication/templates/login.html | 5 +++++
authentication/templates/register.html | 5 +++++
store/templates/store/book_detail.html | 26 +++++++-------------------
3 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/authentication/templates/login.html b/authentication/templates/login.html
index f1006cc..4cad9b8 100644
--- a/authentication/templates/login.html
+++ b/authentication/templates/login.html
@@ -1,6 +1,11 @@
{% extends "store/base.html" %}
+{% block title %}
+Login
+{% endblock %}
+
{% block content %}
+Login