tests.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from django.http import Http404
  2. from django.shortcuts import get_list_or_404, get_object_or_404
  3. from django.test import TestCase
  4. from .models import Article, Author
  5. class GetObjectOr404Tests(TestCase):
  6. def test_get_object_or_404(self):
  7. a1 = Author.objects.create(name="Brave Sir Robin")
  8. a2 = Author.objects.create(name="Patsy")
  9. # No Articles yet, so we should get an Http404 error.
  10. with self.assertRaises(Http404):
  11. get_object_or_404(Article, title="Foo")
  12. article = Article.objects.create(title="Run away!")
  13. article.authors.set([a1, a2])
  14. # get_object_or_404 can be passed a Model to query.
  15. self.assertEqual(
  16. get_object_or_404(Article, title__contains="Run"),
  17. article
  18. )
  19. # We can also use the Article manager through an Author object.
  20. self.assertEqual(
  21. get_object_or_404(a1.article_set, title__contains="Run"),
  22. article
  23. )
  24. # No articles containing "Camelot". This should raise an Http404 error.
  25. with self.assertRaises(Http404):
  26. get_object_or_404(a1.article_set, title__contains="Camelot")
  27. # Custom managers can be used too.
  28. self.assertEqual(
  29. get_object_or_404(Article.by_a_sir, title="Run away!"),
  30. article
  31. )
  32. # QuerySets can be used too.
  33. self.assertEqual(
  34. get_object_or_404(Article.objects.all(), title__contains="Run"),
  35. article
  36. )
  37. # Just as when using a get() lookup, you will get an error if more than
  38. # one object is returned.
  39. with self.assertRaises(Author.MultipleObjectsReturned):
  40. get_object_or_404(Author.objects.all())
  41. # Using an empty QuerySet raises an Http404 error.
  42. with self.assertRaises(Http404):
  43. get_object_or_404(Article.objects.none(), title__contains="Run")
  44. # get_list_or_404 can be used to get lists of objects
  45. self.assertEqual(
  46. get_list_or_404(a1.article_set, title__icontains="Run"),
  47. [article]
  48. )
  49. # Http404 is returned if the list is empty.
  50. with self.assertRaises(Http404):
  51. get_list_or_404(a1.article_set, title__icontains="Shrubbery")
  52. # Custom managers can be used too.
  53. self.assertEqual(
  54. get_list_or_404(Article.by_a_sir, title__icontains="Run"),
  55. [article]
  56. )
  57. # QuerySets can be used too.
  58. self.assertEqual(
  59. get_list_or_404(Article.objects.all(), title__icontains="Run"),
  60. [article]
  61. )
  62. def test_bad_class(self):
  63. # Given an argument klass that is not a Model, Manager, or Queryset
  64. # raises a helpful ValueError message
  65. msg = "First argument to get_object_or_404() must be a Model, Manager, or QuerySet, not 'str'."
  66. with self.assertRaisesMessage(ValueError, msg):
  67. get_object_or_404("Article", title__icontains="Run")
  68. class CustomClass:
  69. pass
  70. msg = "First argument to get_object_or_404() must be a Model, Manager, or QuerySet, not 'CustomClass'."
  71. with self.assertRaisesMessage(ValueError, msg):
  72. get_object_or_404(CustomClass, title__icontains="Run")
  73. # Works for lists too
  74. msg = "First argument to get_list_or_404() must be a Model, Manager, or QuerySet, not 'list'."
  75. with self.assertRaisesMessage(ValueError, msg):
  76. get_list_or_404([Article], title__icontains="Run")
  77. def test_get_object_or_404_queryset_attribute_error(self):
  78. """AttributeError raised by QuerySet.get() isn't hidden."""
  79. with self.assertRaisesMessage(AttributeError, 'AttributeErrorManager'):
  80. get_object_or_404(Article.attribute_error_objects, id=42)
  81. def test_get_list_or_404_queryset_attribute_error(self):
  82. """AttributeError raised by QuerySet.filter() isn't hidden."""
  83. with self.assertRaisesMessage(AttributeError, 'AttributeErrorManager'):
  84. get_list_or_404(Article.attribute_error_objects, title__icontains='Run')