Is That Your Final Answer?
We end up with a view class that looks like this:
lists/views.py (ch31l010).
class
ViewAndAddToList
(
CreateView
,
SingleObjectMixin
):
template_name
=
'list.html'
model
=
List
form_class
=
ExistingListItemForm
def
get_form
(
self
,
form_class
):
self
.
object
=
self
.
get_object
()
return
form_class
(
for_list
=
self
.
object
,
data
=
self
.
request
.
POST
)
Compare Old and New
Let’s see the old version for comparison?
lists/views.py.
def
view_list
(
request
,
list_id
):
list_
=
List
.
objects
.
get
(
id
=
list_id
)
form
=
ExistingListItemForm
(
for_list
=
list_
)
if
request
.
method
==
'POST'
:
form
=
ExistingListItemForm
(
for_list
=
list_
,
data
=
request
.
POST
)
if
form
.
is_valid
():
form
.
save
()
return
redirect
(
list_
)
return
render
(
request
,
'list.html'
, {
'list'
:
list_
,
"form"
:
form
})
Well, it has reduced the number of lines of code from nine to seven. Still, I find the
function-based version a little easier to understand, in that it has a little bit less magic
—“explicit is better than implicit”, as the Zen of Python would have it. I mean …
Sin
gleObjectMixin
? What? And, more offensively, the whole thing falls apart if we don’t
assign to
self.object
inside
get_form
? Yuck.
Still, I guess some of it is in the eye of the beholder.
Best Practices for Unit Testing CBGVs?
As I was working through this, I felt like my “unit” tests were sometimes a little too high-
level. This is no surprise, since tests for views that involve the Django test client are
probably more properly called integrated tests.
They told me whether I was getting things right or wrong, but they didn’t always offer
enough clues on exactly how to fix things.
I occasionally wondered whether there might be some mileage in a test that was closer
to the implementation—something like this:
420
|
Appendix B: Django Class-Based Views