Coverage for app / forms.py: 100%
35 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-06 04:49 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-06 04:49 +0000
1from flask_wtf import FlaskForm
2from wtforms import StringField, IntegerField, TextAreaField, URLField, HiddenField
3from wtforms.fields.numeric import DecimalField
4from wtforms.validators import DataRequired, Optional, Length, NumberRange, URL
6from app.helpers.validators import ValidImageUrl, ValidAmazonLink
9class BookForm(FlaskForm):
10 # ID field (Optional)
11 id = IntegerField("ID", validators=[Optional()])
13 # Author (Required)
14 author = StringField(
15 "Author",
16 validators=[
17 DataRequired(message="The author is required."),
18 Length(max=255, message="The author name cannot exceed 255 characters.")
19 ]
20 )
22 # Title (Required)
23 title = StringField(
24 "Title",
25 validators=[
26 DataRequired(message="The title is required."),
27 Length(max=255, message="The title cannot exceed 255 characters.")
28 ]
29 )
31 # ASIN (Optional)
32 asin = StringField(
33 "ASIN",
34 validators=[
35 Optional(),
36 Length(max=20, message="ASIN must not exceed 20 characters.")
37 ]
38 )
40 # Description (Optional)
41 book_description = TextAreaField(
42 "Description",
43 validators=[
44 Optional(),
45 Length(max=4096, message="The description cannot exceed 4096 characters.")
46 ]
47 )
49 # Rating (Optional but must be between 0 and 5 if provided)
50 rating = DecimalField(
51 "Rating",
52 places=1,
53 validators=[
54 Optional(),
55 NumberRange(min=0, max=5, message="Rating must be between 1 and 5.")
56 ],
57 filters=[lambda x: float(x) if x else None] # Converts valid strings to float
58 )
60 # Book Cover Image URL (Optional but must be a valid URL if provided)
61 image = URLField(
62 "Cover Image URL",
63 validators=[
64 Optional(),
65 ValidImageUrl(message="Must be a valid image URL.")
66 ]
67 )
69 # Amazon Purchase URL (Optional but must be a valid URL if provided)
70 link = URLField(
71 "Amazon URL",
72 validators=[
73 Optional(),
74 ValidAmazonLink()
75 ]
76 )
78 # Categories, required)
79 categories_flat = StringField(
80 "Categories",
81 validators=[
82 DataRequired(message="The category string is required."),
83 Length(max=255,
84 message="The category string is ' > ' separated and cannot exceed 255 chars.")
85 ]
86 )
88 # Pages (Optional but must be positive)
89 hardcover = StringField(
90 "Pages",
91 validators=[
92 Optional(),
93 Length(max=64, message="Pages string must not exceed 64 characters.")
94 ]
95 )
97 # ISBN-10 (Optional)
98 isbn_10 = StringField(
99 "ISBN-10",
100 validators=[
101 Optional(),
102 Length(max=13, message="ISBN-10 must not exceed 13 characters.")
103 ]
104 )
106 # ISBN-13 (Optional, 13 characters)
107 isbn_13 = StringField(
108 "ISBN-13",
109 validators=[
110 Optional(),
111 Length(max=17, message="ISBN-13 must not exceed 13 characters.")
112 ]
113 )
115 # Bestsellers Rank (Optional)
116 bestsellers_rank_flat = TextAreaField(
117 "Bestsellers Rank",
118 validators=[
119 Optional(),
120 Length(max=4096, message="Bestsellers Rank cannot exceed 4096 characters.")
121 ]
122 )
124 # Specifications (Optional)
125 specifications_flat = TextAreaField(
126 "Specifications",
127 validators=[
128 Optional(),
129 Length(max=4096, message="Specifications cannot exceed 4096 characters.")
130 ]
131 )
133 # Next (Hidden Field)
134 next = HiddenField("next")
136 def fill_from_book(self, book):
137 """
138 Populate the form fields from a Book object.
139 """
140 self.title.data = book.title
141 self.author.data = book.author
142 self.book_description.data = book.book_description
143 self.specifications_flat.data = book.specifications_flat
144 self.asin.data = book.asin
145 self.bestsellers_rank_flat.data = book.bestsellers_rank_flat
146 self.categories_flat.data = book.categories_flat
147 self.hardcover.data = book.hardcover
148 self.image.data = book.image
149 self.isbn_10.data = book.isbn_10
150 self.isbn_13.data = book.isbn_13
151 self.link.data = book.link
152 self.rating.data = book.rating