Coverage for catalog/views.py: 96.88%
92 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-13 15:39 -0700
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-13 15:39 -0700
1import datetime
3from django.contrib.auth.decorators import login_required, permission_required
4from django.contrib.auth.mixins import (
5 LoginRequiredMixin,
6 PermissionRequiredMixin,
7)
8from django.db.models import Q
9from django.http import HttpResponseRedirect
10from django.shortcuts import get_object_or_404, render
11from django.urls import reverse, reverse_lazy
12from django.views.generic import (
13 CreateView,
14 DeleteView,
15 DetailView,
16 ListView,
17 UpdateView,
18)
20from .forms import RenewBookForm
21from .models import Author, Book, BookInstance
24def index(request):
25 num_books = Book.objects.all().count()
26 num_instances = BookInstance.objects.all().count()
27 num_instances_available = BookInstance.objects.filter(status__exact="a").count()
28 num_authors = Author.objects.count()
29 num_visits = request.session.get("num_visits", 0)
30 request.session["num_visits"] = num_visits + 1
31 context = {
32 "num_books": num_books,
33 "num_instances": num_instances,
34 "num_instances_available": num_instances_available,
35 "num_authors": num_authors,
36 "num_visits": num_visits,
37 }
39 return render(request, "index.html", context=context)
42class BookListView(ListView):
43 """Generic class-based view for a list of books."""
45 model = Book
46 paginate_by = 10
49class BookDetailView(DetailView):
50 """Generic class-based detail view for a book."""
52 model = Book
55class AuthorListView(ListView):
56 """Generic class-based list view for a list of authors."""
58 model = Author
59 paginate_by = 10
62class AuthorDetailView(DetailView):
63 """Generic class-based detail view for an author."""
65 model = Author
68class LoanedBooksByUserListView(LoginRequiredMixin, ListView):
69 model = BookInstance
70 template_name = "catalog/bookinstance_list_borrowed_user.html"
71 paginate_by = 10
73 def get_queryset(self):
74 return ( 1ghij
75 BookInstance.objects.filter(borrower=self.request.user)
76 .filter(status__exact="o")
77 .order_by("due_back")
78 )
81class LoanedBooksAllListView(PermissionRequiredMixin, ListView):
82 model = BookInstance
83 permission_required = "catalog.can_mark_returned"
84 template_name = "catalog/bookinstance_list_borrowed_all.html"
85 paginate_by = 10
87 def get_queryset(self):
88 return BookInstance.objects.filter(status__exact="o").order_by("due_back") 1b
91@login_required
92@permission_required("catalog.can_mark_returned", raise_exception=True)
93def renew_book_librarian(request, pk):
94 """View function for renewing a specific BookInstance by librarian."""
95 book_instance = get_object_or_404(BookInstance, pk=pk) 1kcdebf
97 # If this is a POST request then process the Form data
98 if request.method == "POST": 1cdebf
99 # Create a form instance and populate it with data
100 # from the request (binding):
101 form = RenewBookForm(request.POST) 1b
103 # Check if the form is valid:
104 if form.is_valid(): 104 ↛ 118line 104 didn't jump to line 118 because the condition on line 104 was always true1b
105 # process the data in form.cleaned_data as required (here we
106 # just write it to the model due_back field)
107 book_instance.due_back = form.cleaned_data["renewal_date"] 1b
108 book_instance.save() 1b
110 # redirect to a new URL:
111 return HttpResponseRedirect(reverse("all-borrowed")) 1b
113 # If this is a GET (or any other method) create the default form
114 else:
115 proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) 1cdef
116 form = RenewBookForm(initial={"renewal_date": proposed_renewal_date}) 1cdef
118 context = { 1cdef
119 "form": form,
120 "book_instance": book_instance,
121 }
123 return render(request, "catalog/book_renew_librarian.html", context) 1cdef
126class AuthorCreate(PermissionRequiredMixin, CreateView):
127 model = Author
128 fields = ["first_name", "last_name", "date_of_birth", "date_of_death"]
129 initial = {"date_of_birth": "02/02/1882"}
130 permission_required = "catalog.can_mark_returned"
131 template_name = "catalog/author_create.html"
134class AuthorUpdate(PermissionRequiredMixin, UpdateView):
135 model = Author
136 fields = [
137 "first_name",
138 "last_name",
139 "middle_name",
140 "date_of_birth",
141 "date_of_death",
142 ]
143 permission_required = "catalog.can_mark_returned"
144 template_name = "catalog/author_update.html"
147class AuthorDelete(PermissionRequiredMixin, DeleteView):
148 model = Author
149 permission_required = "catalog.can_mark_returned"
150 success_url = reverse_lazy("authors")
153class BookCreate(PermissionRequiredMixin, CreateView):
154 model = Book
155 fields = [
156 "title",
157 "author",
158 "pages",
159 "publisher",
160 "pubdate",
161 "summary",
162 "isbn",
163 "genre",
164 "language",
165 ]
166 permission_required = "catalog.can_mark_returned"
167 template_name = "catalog/book_create.html"
170class BookUpdate(PermissionRequiredMixin, UpdateView):
171 model = Book
172 fields = [
173 "title",
174 "author",
175 "pages",
176 "publisher",
177 "pubdate",
178 "summary",
179 "isbn",
180 "genre",
181 "language",
182 ]
183 permission_required = "catalog.can_mark_returned"
184 template_name = "catalog/book_update.html"
187class BookDelete(PermissionRequiredMixin, DeleteView):
188 model = Book
189 success_url = reverse_lazy("books")
190 permission_required = "catalog.can_mark_returned"
193class SearchResultsListView(ListView):
194 model = Book
195 context_object_name = "books"
196 template_name = "catalog/search_results.html"
198 def get_queryset(self):
199 query = self.request.GET.get("q")
200 return Book.objects.filter(
201 Q(title__icontains=query)
202 | Q(author__first_name__icontains=query)
203 | Q(author__middle_name__icontains=query)
204 | Q(author__last_name__icontains=query)
205 | Q(language__name__icontains=query)
206 | Q(publisher__icontains=query)
207 | Q(pubdate__icontains=query)
208 | Q(genre__name=query)
209 ).distinct()