1. from django.contrib.auth.decorators import login_required
    
  2. from django.core.paginator import Paginator
    
  3. from django.urls import reverse, reverse_lazy
    
  4. from django.utils.decorators import method_decorator
    
  5. from django.views import generic
    
  6. 
    
  7. from .forms import AuthorForm, ConfirmDeleteForm, ContactForm
    
  8. from .models import Artist, Author, Book, BookSigning, Page
    
  9. 
    
  10. 
    
  11. class CustomTemplateView(generic.TemplateView):
    
  12.     template_name = "generic_views/about.html"
    
  13. 
    
  14.     def get_context_data(self, **kwargs):
    
  15.         context = super().get_context_data(**kwargs)
    
  16.         context.update({"key": "value"})
    
  17.         return context
    
  18. 
    
  19. 
    
  20. class ObjectDetail(generic.DetailView):
    
  21.     template_name = "generic_views/detail.html"
    
  22. 
    
  23.     def get_object(self):
    
  24.         return {"foo": "bar"}
    
  25. 
    
  26. 
    
  27. class ArtistDetail(generic.DetailView):
    
  28.     queryset = Artist.objects.all()
    
  29. 
    
  30. 
    
  31. class AuthorDetail(generic.DetailView):
    
  32.     queryset = Author.objects.all()
    
  33. 
    
  34. 
    
  35. class AuthorCustomDetail(generic.DetailView):
    
  36.     template_name = "generic_views/author_detail.html"
    
  37.     queryset = Author.objects.all()
    
  38. 
    
  39.     def get(self, request, *args, **kwargs):
    
  40.         # Ensures get_context_object_name() doesn't reference self.object.
    
  41.         author = self.get_object()
    
  42.         context = {"custom_" + self.get_context_object_name(author): author}
    
  43.         return self.render_to_response(context)
    
  44. 
    
  45. 
    
  46. class PageDetail(generic.DetailView):
    
  47.     queryset = Page.objects.all()
    
  48.     template_name_field = "template"
    
  49. 
    
  50. 
    
  51. class DictList(generic.ListView):
    
  52.     """A ListView that doesn't use a model."""
    
  53. 
    
  54.     queryset = [{"first": "John", "last": "Lennon"}, {"first": "Yoko", "last": "Ono"}]
    
  55.     template_name = "generic_views/list.html"
    
  56. 
    
  57. 
    
  58. class ArtistList(generic.ListView):
    
  59.     template_name = "generic_views/list.html"
    
  60.     queryset = Artist.objects.all()
    
  61. 
    
  62. 
    
  63. class AuthorList(generic.ListView):
    
  64.     queryset = Author.objects.all()
    
  65. 
    
  66. 
    
  67. class AuthorListGetQuerysetReturnsNone(AuthorList):
    
  68.     def get_queryset(self):
    
  69.         return None
    
  70. 
    
  71. 
    
  72. class BookList(generic.ListView):
    
  73.     model = Book
    
  74. 
    
  75. 
    
  76. class CustomPaginator(Paginator):
    
  77.     def __init__(self, queryset, page_size, orphans=0, allow_empty_first_page=True):
    
  78.         super().__init__(
    
  79.             queryset,
    
  80.             page_size,
    
  81.             orphans=2,
    
  82.             allow_empty_first_page=allow_empty_first_page,
    
  83.         )
    
  84. 
    
  85. 
    
  86. class AuthorListCustomPaginator(AuthorList):
    
  87.     paginate_by = 5
    
  88. 
    
  89.     def get_paginator(
    
  90.         self, queryset, page_size, orphans=0, allow_empty_first_page=True
    
  91.     ):
    
  92.         return super().get_paginator(
    
  93.             queryset,
    
  94.             page_size,
    
  95.             orphans=2,
    
  96.             allow_empty_first_page=allow_empty_first_page,
    
  97.         )
    
  98. 
    
  99. 
    
  100. class ContactView(generic.FormView):
    
  101.     form_class = ContactForm
    
  102.     success_url = reverse_lazy("authors_list")
    
  103.     template_name = "generic_views/form.html"
    
  104. 
    
  105. 
    
  106. class ArtistCreate(generic.CreateView):
    
  107.     model = Artist
    
  108.     fields = "__all__"
    
  109. 
    
  110. 
    
  111. class NaiveAuthorCreate(generic.CreateView):
    
  112.     queryset = Author.objects.all()
    
  113.     fields = "__all__"
    
  114. 
    
  115. 
    
  116. class TemplateResponseWithoutTemplate(
    
  117.     generic.detail.SingleObjectTemplateResponseMixin, generic.View
    
  118. ):
    
  119.     # we don't define the usual template_name here
    
  120. 
    
  121.     def __init__(self):
    
  122.         # Dummy object, but attr is required by get_template_name()
    
  123.         self.object = None
    
  124. 
    
  125. 
    
  126. class AuthorCreate(generic.CreateView):
    
  127.     model = Author
    
  128.     success_url = "/list/authors/"
    
  129.     fields = "__all__"
    
  130. 
    
  131. 
    
  132. class SpecializedAuthorCreate(generic.CreateView):
    
  133.     model = Author
    
  134.     form_class = AuthorForm
    
  135.     template_name = "generic_views/form.html"
    
  136.     context_object_name = "thingy"
    
  137. 
    
  138.     def get_success_url(self):
    
  139.         return reverse("author_detail", args=[self.object.id])
    
  140. 
    
  141. 
    
  142. class AuthorCreateRestricted(AuthorCreate):
    
  143.     post = method_decorator(login_required)(AuthorCreate.post)
    
  144. 
    
  145. 
    
  146. class ArtistUpdate(generic.UpdateView):
    
  147.     model = Artist
    
  148.     fields = "__all__"
    
  149. 
    
  150. 
    
  151. class NaiveAuthorUpdate(generic.UpdateView):
    
  152.     queryset = Author.objects.all()
    
  153.     fields = "__all__"
    
  154. 
    
  155. 
    
  156. class AuthorUpdate(generic.UpdateView):
    
  157.     get_form_called_count = 0  # Used to ensure get_form() is called once.
    
  158.     model = Author
    
  159.     success_url = "/list/authors/"
    
  160.     fields = "__all__"
    
  161. 
    
  162.     def get_form(self, *args, **kwargs):
    
  163.         self.get_form_called_count += 1
    
  164.         return super().get_form(*args, **kwargs)
    
  165. 
    
  166. 
    
  167. class OneAuthorUpdate(generic.UpdateView):
    
  168.     success_url = "/list/authors/"
    
  169.     fields = "__all__"
    
  170. 
    
  171.     def get_object(self):
    
  172.         return Author.objects.get(pk=1)
    
  173. 
    
  174. 
    
  175. class SpecializedAuthorUpdate(generic.UpdateView):
    
  176.     model = Author
    
  177.     form_class = AuthorForm
    
  178.     template_name = "generic_views/form.html"
    
  179.     context_object_name = "thingy"
    
  180. 
    
  181.     def get_success_url(self):
    
  182.         return reverse("author_detail", args=[self.object.id])
    
  183. 
    
  184. 
    
  185. class NaiveAuthorDelete(generic.DeleteView):
    
  186.     queryset = Author.objects.all()
    
  187. 
    
  188. 
    
  189. class AuthorDelete(generic.DeleteView):
    
  190.     model = Author
    
  191.     success_url = "/list/authors/"
    
  192. 
    
  193. 
    
  194. class AuthorDeleteFormView(generic.DeleteView):
    
  195.     model = Author
    
  196.     form_class = ConfirmDeleteForm
    
  197. 
    
  198.     def get_success_url(self):
    
  199.         return reverse("authors_list")
    
  200. 
    
  201. 
    
  202. class SpecializedAuthorDelete(generic.DeleteView):
    
  203.     queryset = Author.objects.all()
    
  204.     template_name = "generic_views/confirm_delete.html"
    
  205.     context_object_name = "thingy"
    
  206.     success_url = reverse_lazy("authors_list")
    
  207. 
    
  208. 
    
  209. class BookConfig:
    
  210.     queryset = Book.objects.all()
    
  211.     date_field = "pubdate"
    
  212. 
    
  213. 
    
  214. class BookArchive(BookConfig, generic.ArchiveIndexView):
    
  215.     pass
    
  216. 
    
  217. 
    
  218. class BookYearArchive(BookConfig, generic.YearArchiveView):
    
  219.     pass
    
  220. 
    
  221. 
    
  222. class BookMonthArchive(BookConfig, generic.MonthArchiveView):
    
  223.     pass
    
  224. 
    
  225. 
    
  226. class BookWeekArchive(BookConfig, generic.WeekArchiveView):
    
  227.     pass
    
  228. 
    
  229. 
    
  230. class BookDayArchive(BookConfig, generic.DayArchiveView):
    
  231.     pass
    
  232. 
    
  233. 
    
  234. class BookTodayArchive(BookConfig, generic.TodayArchiveView):
    
  235.     pass
    
  236. 
    
  237. 
    
  238. class BookDetail(BookConfig, generic.DateDetailView):
    
  239.     pass
    
  240. 
    
  241. 
    
  242. class AuthorGetQuerySetFormView(generic.edit.ModelFormMixin):
    
  243.     fields = "__all__"
    
  244. 
    
  245.     def get_queryset(self):
    
  246.         return Author.objects.all()
    
  247. 
    
  248. 
    
  249. class BookDetailGetObjectCustomQueryset(BookDetail):
    
  250.     def get_object(self, queryset=None):
    
  251.         return super().get_object(queryset=Book.objects.filter(pk=self.kwargs["pk"]))
    
  252. 
    
  253. 
    
  254. class CustomMultipleObjectMixinView(generic.list.MultipleObjectMixin, generic.View):
    
  255.     queryset = [
    
  256.         {"name": "John"},
    
  257.         {"name": "Yoko"},
    
  258.     ]
    
  259. 
    
  260.     def get(self, request):
    
  261.         self.object_list = self.get_queryset()
    
  262. 
    
  263. 
    
  264. class CustomContextView(generic.detail.SingleObjectMixin, generic.View):
    
  265.     model = Book
    
  266.     object = Book(name="dummy")
    
  267. 
    
  268.     def get_object(self):
    
  269.         return Book(name="dummy")
    
  270. 
    
  271.     def get_context_data(self, **kwargs):
    
  272.         context = {"custom_key": "custom_value"}
    
  273.         context.update(kwargs)
    
  274.         return super().get_context_data(**context)
    
  275. 
    
  276.     def get_context_object_name(self, obj):
    
  277.         return "test_name"
    
  278. 
    
  279. 
    
  280. class CustomSingleObjectView(generic.detail.SingleObjectMixin, generic.View):
    
  281.     model = Book
    
  282.     object = Book(name="dummy")
    
  283. 
    
  284. 
    
  285. class BookSigningConfig:
    
  286.     model = BookSigning
    
  287.     date_field = "event_date"
    
  288.     # use the same templates as for books
    
  289. 
    
  290.     def get_template_names(self):
    
  291.         return ["generic_views/book%s.html" % self.template_name_suffix]
    
  292. 
    
  293. 
    
  294. class BookSigningArchive(BookSigningConfig, generic.ArchiveIndexView):
    
  295.     pass
    
  296. 
    
  297. 
    
  298. class BookSigningYearArchive(BookSigningConfig, generic.YearArchiveView):
    
  299.     pass
    
  300. 
    
  301. 
    
  302. class BookSigningMonthArchive(BookSigningConfig, generic.MonthArchiveView):
    
  303.     pass
    
  304. 
    
  305. 
    
  306. class BookSigningWeekArchive(BookSigningConfig, generic.WeekArchiveView):
    
  307.     pass
    
  308. 
    
  309. 
    
  310. class BookSigningDayArchive(BookSigningConfig, generic.DayArchiveView):
    
  311.     pass
    
  312. 
    
  313. 
    
  314. class BookSigningTodayArchive(BookSigningConfig, generic.TodayArchiveView):
    
  315.     pass
    
  316. 
    
  317. 
    
  318. class BookArchiveWithoutDateField(generic.ArchiveIndexView):
    
  319.     queryset = Book.objects.all()
    
  320. 
    
  321. 
    
  322. class BookSigningDetail(BookSigningConfig, generic.DateDetailView):
    
  323.     context_object_name = "book"
    
  324. 
    
  325. 
    
  326. class NonModel:
    
  327.     id = "non_model_1"
    
  328. 
    
  329.     _meta = None
    
  330. 
    
  331. 
    
  332. class NonModelDetail(generic.DetailView):
    
  333.     template_name = "generic_views/detail.html"
    
  334.     model = NonModel
    
  335. 
    
  336.     def get_object(self, queryset=None):
    
  337.         return NonModel()
    
  338. 
    
  339. 
    
  340. class ObjectDoesNotExistDetail(generic.DetailView):
    
  341.     def get_queryset(self):
    
  342.         return Book.does_not_exist.all()
    
  343. 
    
  344. 
    
  345. class LateValidationView(generic.FormView):
    
  346.     form_class = ContactForm
    
  347.     success_url = reverse_lazy("authors_list")
    
  348.     template_name = "generic_views/form.html"
    
  349. 
    
  350.     def form_valid(self, form):
    
  351.         form.add_error(None, "There is an error")
    
  352.         return self.form_invalid(form)