使用Django 1.8和Python 3.4无法捕获DoesNotExist异常

时间:2015-06-16 09:04:19

标签: python django exception python-3.x

我在Django应用程序中有以下视图:

class VideoCreateView(View):
    """
    Handle creating a video
    """
    template_name = 'albums/video_create.html'
    success_template_name = 'albums/video_created.html'

    def get(self, request, *args, **kwargs):
        """
        Display the confirmation dialogue
        """
        # First, get the album
        pk = kwargs['pk']
        try:
            album = Album.objects.get(id=pk)
        except Album.DoesNotExist:
            raise Http404

        # Render the template
        return render(request, self.template_name)

    def post(self, request, *args, **kwargs):
        """
        Generate the video
        """
        # First, get the album
        pk = kwargs['pk']
        try:
            album = Album.objects.get(id=pk)
        except Album.DoesNotExist:
            raise Http404

        # Trigger build
        if len(album.photo_set.all()) > 0:
            celery_generate_video.delay(album)

            # Send response
            return render(request, self.success_template_name)
        else:
            raise HttpResponseBadRequest

这需要URL中相册的ID,如果相册不存在,则应该引发404错误。我已编写以下测试来检查此行为:

@mock.patch('storages.backends.s3boto.S3BotoStorage', FileSystemStorage)
def test_get_does_not_exist(self):
    """
    Test GET requests
    """
    pk = uuid.uuid4()
    url = reverse('video_create', kwargs={
        'pk': pk.urn[9:]
    })
    request = self.factory.get(url)
    request.user = self.user
    response = VideoCreateView.as_view()(request, pk=pk)
    self.assertEqual(response.status_code, 404)

不幸的是,它引发了以下错误:

======================================================================
ERROR: test_get_does_not_exist (albums.tests.VideoCreateViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/matthew/Projects/digitallife/albums/views.py", line 200, in get
    album = Album.objects.get(id=pk)
  File "/home/matthew/Projects/digitallife/venv/lib/python3.4/site-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/matthew/Projects/digitallife/venv/lib/python3.4/site-packages/django/db/models/query.py", line 334, in get
    self.model._meta.object_name
albums.models.DoesNotExist: Album matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/mock.py", line 1125, in patched
    return func(*args, **keywargs)
  File "/home/matthew/Projects/digitallife/albums/tests.py", line 573, in test_get_does_not_exist
    response = VideoCreateView.as_view()(request, pk=pk)
  File "/home/matthew/Projects/digitallife/venv/lib/python3.4/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/matthew/Projects/digitallife/venv/lib/python3.4/site-packages/django/views/generic/base.py", line 89, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/matthew/Projects/digitallife/albums/views.py", line 202, in get
    raise Http404
django.http.response.Http404

在我看来,这个例外并没有被抓住。我之前使用过这种方法来捕获Django中的无效对象,但那是在Python 2.7中,所以我想知道它是否是Python 3中的东西(这是我的第一个Python 3 Django项目)。我做错了什么?

1 个答案:

答案 0 :(得分:4)

你在视图中没有做错任何事。测试结果显示它正在完全按照您的要求执行:捕获DoesNotExist,并在响应中提升Http404。

问题出在你的考试中。您直接调用该视图,这意味着您跳过所有通常执行处理异常并将其转换为404/500响应的中间件。您应该使用内置测试客户端来调用视图,而不是通过工厂创建请求:

url = ...
response = self.client.get(url)