我已经搜索了有关同一错误消息的其他问题,但似乎它应该对我有效(我正在使用Django 2 btw。)
class Book(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(default='')
def save(self, *args, **kwargs):
self.slug = self.name.lower().replace(' ', '_')
我的路径:
path('<slug:slug>', views.BookDetailView.as_view(), name='book-detail'),
观点:
class BookDetailView(DetailView):
model = Book
template_name = 'books/bookdetail.html'
context_object_name = 'book'
但是,它在运行测试时抛出了错误消息(通常通过浏览器请求视图时可以正常工作)。
这是适当的测试功能(使用RequestFactory和混音器)
class TestBookDetailView:
def test_access(self):
mixer.blend('books.Book', name='The Book')
req = RequestFactory().get('/books/the_book')
req.user = mixer.blend(User)
resp = BookDetailView.as_view()(req)
assert resp.status_code == 200, 'Should display detail view'
这是追溯:
_______________________ TestBookDetailView.test_access ________________________
self = <books.tests.test_books_views.TestBookDetailView object at 0x000001C8E3577240>
def test_access(self):
mixer.blend('books.Book', name='The Book')
req = RequestFactory().get('/books/the_book')
req.user = mixer.blend(User)
> resp = BookDetailView.as_view()(req)
books\tests\test_books_views.py:29:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\..\envs\booknote\lib\site-packages\django\views\generic\base.py:69: in view
return self.dispatch(request, *args, **kwargs)
..\..\envs\booknote\lib\site-packages\django\utils\decorators.py:62: in _wrapper
return bound_func(*args, **kwargs)
..\..\envs\booknote\lib\site-packages\django\contrib\auth\decorators.py:21: in _wrapped_view
return view_func(request, *args, **kwargs)
..\..\envs\booknote\lib\site-packages\django\utils\decorators.py:58: in bound_func
return func.__get__(self, type(self))(*args2, **kwargs2)
..\..\envs\booknote\lib\site-packages\django\views\generic\base.py:89: in dispatch
return handler(request, *args, **kwargs)
..\..\envs\booknote\lib\site-packages\django\views\generic\detail.py:105: in get
self.object = self.get_object()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <books.views.BookDetailView object at 0x000001C8E357CD68>
queryset = <QuerySet [<Book: Book object (1)>]>
def get_object(self, queryset=None):
"""
Return the object the view is displaying.
Require `self.queryset` and a `pk` or `slug` argument in the URLconf.
Subclasses can override this to return any object.
"""
# Use a custom queryset if provided; this is required for subclasses
# like DateDetailView
if queryset is None:
queryset = self.get_queryset()
# Next, try looking up by primary key.
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
if pk is not None:
queryset = queryset.filter(pk=pk)
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
# If none of those are defined, it's an error.
if pk is None and slug is None:
raise AttributeError("Generic detail view %s must be called with "
"either an object pk or a slug."
> % self.__class__.__name__)
E AttributeError: Generic detail view BookDetailView must be called with either an object pk or a slug.
..\..\envs\booknote\lib\site-packages\django\views\generic\detail.py:47: AttributeError
我做错了什么?
先谢谢
答案 0 :(得分:2)
您需要在测试中明确传递URL参数。
resp = BookDetailView.as_view()(req, slug="the_book"))
或者使用内置的测试客户端,而不是使用内置的测试客户端:
self.client.force_login(user)
resp = self.client.get("/books/the_book")