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

1import datetime 

2 

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) 

19 

20from .forms import RenewBookForm 

21from .models import Author, Book, BookInstance 

22 

23 

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 } 

38 

39 return render(request, "index.html", context=context) 

40 

41 

42class BookListView(ListView): 

43 """Generic class-based view for a list of books.""" 

44 

45 model = Book 

46 paginate_by = 10 

47 

48 

49class BookDetailView(DetailView): 

50 """Generic class-based detail view for a book.""" 

51 

52 model = Book 

53 

54 

55class AuthorListView(ListView): 

56 """Generic class-based list view for a list of authors.""" 

57 

58 model = Author 

59 paginate_by = 10 

60 

61 

62class AuthorDetailView(DetailView): 

63 """Generic class-based detail view for an author.""" 

64 

65 model = Author 

66 

67 

68class LoanedBooksByUserListView(LoginRequiredMixin, ListView): 

69 model = BookInstance 

70 template_name = "catalog/bookinstance_list_borrowed_user.html" 

71 paginate_by = 10 

72 

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 ) 

79 

80 

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 

86 

87 def get_queryset(self): 

88 return BookInstance.objects.filter(status__exact="o").order_by("due_back") 1b

89 

90 

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

96 

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

102 

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

109 

110 # redirect to a new URL: 

111 return HttpResponseRedirect(reverse("all-borrowed")) 1b

112 

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

117 

118 context = { 1cdef

119 "form": form, 

120 "book_instance": book_instance, 

121 } 

122 

123 return render(request, "catalog/book_renew_librarian.html", context) 1cdef

124 

125 

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" 

132 

133 

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" 

145 

146 

147class AuthorDelete(PermissionRequiredMixin, DeleteView): 

148 model = Author 

149 permission_required = "catalog.can_mark_returned" 

150 success_url = reverse_lazy("authors") 

151 

152 

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" 

168 

169 

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" 

185 

186 

187class BookDelete(PermissionRequiredMixin, DeleteView): 

188 model = Book 

189 success_url = reverse_lazy("books") 

190 permission_required = "catalog.can_mark_returned" 

191 

192 

193class SearchResultsListView(ListView): 

194 model = Book 

195 context_object_name = "books" 

196 template_name = "catalog/search_results.html" 

197 

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()