Index: tests/modeltests/prefetch_related/tests.py
===================================================================
--- tests/modeltests/prefetch_related/tests.py	(revision 17890)
+++ tests/modeltests/prefetch_related/tests.py	(working copy)
@@ -68,6 +68,14 @@
 
         self.assertQuerysetEqual(self.book2.authors.all(), [u"<Author: Charlotte>"])
 
+    def test_onetoone_reverse_no_match(self):
+        # Regression for #17439
+        with self.assertNumQueries(2):
+            book = Book.objects.prefetch_related('bookwithyear').all()[0]
+        with self.assertNumQueries(0):
+            with self.assertRaises(BookWithYear.DoesNotExist):
+                book.bookwithyear
+
     def test_survives_clone(self):
         with self.assertNumQueries(2):
             lists = [list(b.first_time_authors.all())
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 17890)
+++ django/db/models/query.py	(working copy)
@@ -6,6 +6,7 @@
 import itertools
 import sys
 
+from django.core import exceptions
 from django.db import connections, router, transaction, IntegrityError
 from django.db.models.fields import AutoField
 from django.db.models.query_utils import (Q, select_related_descend,
@@ -1677,14 +1678,21 @@
                 # (e.g. via select_related), or hopefully some other property
                 # that doesn't support prefetching but needs to be traversed.
 
-                # We replace the current list of parent objects with that list.
-                obj_list = [getattr(obj, attr) for obj in obj_list]
+                # We replace the current list of parent objects with that list,
+                # filtering out empty or missing values so that we can continue
+                # with nullable or reverse relations.
+                new_obj_list = []
+                for obj in obj_list:
+                    try:
+                        new_obj = getattr(obj, attr)
+                    except exceptions.ObjectDoesNotExist:
+                        continue
+                    if new_obj is None:
+                        continue
+                    new_obj_list.append(new_obj)
+                obj_list = new_obj_list
 
-                # Filter out 'None' so that we can continue with nullable
-                # relations.
-                obj_list = [obj for obj in obj_list if obj is not None]
 
-
 def get_prefetcher(instance, attr):
     """
     For the attribute 'attr' on the given instance, finds
@@ -1778,8 +1786,7 @@
         vals = rel_obj_cache.get(instance_attr_val, [])
         if single:
             # Need to assign to single cache on instance
-            if vals:
-                setattr(obj, cache_name, vals[0])
+            setattr(obj, cache_name, vals[0] if vals else None)
         else:
             # Multi, attribute represents a manager with an .all() method that
             # returns a QuerySet
