Coverage for catalog/models.py: 94.29%
68 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-29 10:34 -0700
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-29 10:34 -0700
1import uuid 1a
2from datetime import date 1a
3from typing import ClassVar 1a
5from django.contrib.auth import get_user_model 1a
6from django.db import models 1a
7from django.urls import reverse 1a
10class Genre(models.Model): 1a
11 name = models.CharField(max_length=200, help_text="Enter a book genre") 1a
13 class Meta: 1a
14 ordering: ClassVar[list[str]] = ["name"] 1a
16 def __str__(self): 1a
17 return self.name 1a
20class Language(models.Model): 1a
21 name = models.CharField(max_length=200, help_text="Enter the book's language") 1a
23 class Meta: 1a
24 ordering: ClassVar[list[str]] = ["name"] 1a
26 def __str__(self): 1a
27 return self.name 1a
30class Book(models.Model): 1a
31 title = models.CharField(max_length=200) 1a
32 author = models.ForeignKey("Author", on_delete=models.SET_NULL, null=True) 1a
33 pages = models.IntegerField(null=True, blank=True, help_text="Number of Pages") 1a
34 publisher = models.CharField(max_length=40, blank=True) 1a
35 pubdate = models.DateField(null=True, blank=True, help_text="Date Published") 1a
36 summary = models.TextField( 1a
37 max_length=1000, help_text="Enter a brief description of the book."
38 )
39 isbn = models.CharField( 1a
40 "ISBN",
41 max_length=13,
42 unique=True,
43 help_text="13 Character <a href='https://www.isbn-international.org/content/what-isbn'>ISBN number</a>",
44 )
45 genre = models.ManyToManyField(Genre, help_text="Select a genre for this book") 1a
46 language = models.ForeignKey("Language", on_delete=models.SET_NULL, null=True) 1a
47 cover = models.ImageField(upload_to="covers/", blank=True) 1a
49 class Meta: 1a
50 ordering: ClassVar[list[str]] = ["title", "author"] 1a
52 def __str__(self): 1a
53 return self.title 1a
55 def get_absolute_url(self): 1a
56 return reverse("book-detail", args=[str(self.id)]) 1a
58 def display_genre(self): 1a
59 """Creates a string for Genre. Required for Admin display"""
60 return ", ".join([genre.name for genre in self.genre.all()[:3]])
62 display_genre.short_description = "Genre" 1a
65class BookInstance(models.Model): 1a
66 """Represents a specific copy of a book"""
68 id = models.UUIDField( 1a
69 primary_key=True,
70 default=uuid.uuid4,
71 help_text="Unique ID for this book across whole library",
72 )
73 book = models.ForeignKey("Book", on_delete=models.RESTRICT, null=True) 1a
74 imprint = models.CharField(max_length=200) 1a
75 due_back = models.DateField(null=True, blank=True) 1a
76 borrower = models.ForeignKey( 1a
77 get_user_model(), on_delete=models.SET_NULL, null=True, blank=True
78 )
80 LOAN_STATUS = ( 1a
81 ("m", "Maintenance"),
82 ("o", "On Loan"),
83 ("a", "Available"),
84 ("r", "Reserved"),
85 )
87 status = models.CharField( 1a
88 max_length=1,
89 choices=LOAN_STATUS,
90 blank=True,
91 default="m",
92 help_text="Book Availability",
93 )
95 class Meta: 1a
96 ordering: ClassVar[list[str]] = ["due_back"] 1a
97 permissions = (("can_mark_returned", "Set book as returned"),) 1a
99 def __str__(self): 1a
100 return f"{self.id} ({self.book.title})"
102 @property 1a
103 def is_overdue(self): 1a
104 return bool(self.due_back and date.today() > self.due_back) 1a
107class Author(models.Model): 1a
108 first_name = models.CharField(max_length=100) 1a
109 middle_name = models.CharField( 1a
110 max_length=100, blank=True, help_text="Middle Name(initial)"
111 )
112 last_name = models.CharField(max_length=100) 1a
113 date_of_birth = models.DateField(null=True, blank=True) 1a
114 date_of_death = models.DateField("Died", null=True, blank=True) 1a
116 class Meta: 1a
117 ordering: ClassVar[list[str]] = ["last_name", "first_name"] 1a
119 def __str__(self): 1a
120 if self.middle_name is not None: 120 ↛ 123line 120 didn't jump to line 123 because the condition on line 120 was always true1a
121 return f"{self.last_name}, {self.first_name} {self.middle_name}" 1a
122 else:
123 return f"{self.last_name}, {self.first_name}"
125 def get_absolute_url(self): 1a
126 return reverse("author-detail", args=[str(self.id)]) 1a