diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py
index a0d02bc8bb..b51cf9a782 100644
--- a/django/views/decorators/http.py
+++ b/django/views/decorators/http.py
@@ -75,7 +75,15 @@ def condition(etag_func=None, last_modified_func=None):
             if if_none_match or if_match:
                 # There can be more than one ETag in the request, so we
                 # consider the list of values.
-                etags = parse_etags(if_none_match or if_match)
+                try:
+                    etags = parse_etags(if_none_match or if_match)
+                except ValueError:
+                    # In case of invalid etag ignore all ETag headers.
+                    # Apparently Opera sends invalidly quoted headers at times
+                    # (we should be returning a 400 response, but that's a
+                    # little extreme) -- this is Django bug #10681.
+                    if_none_match = None
+                    if_match = None
 
             # Compute values (if any) for the requested resource.
             if etag_func:
diff --git a/tests/regressiontests/conditional_processing/models.py b/tests/regressiontests/conditional_processing/models.py
index 756244ab3b..b291aed337 100644
--- a/tests/regressiontests/conditional_processing/models.py
+++ b/tests/regressiontests/conditional_processing/models.py
@@ -112,6 +112,11 @@ class ConditionalGet(TestCase):
         response = self.client.get('/condition/last_modified2/')
         self.assertFullResponse(response, check_etag=False)
 
+    def testInvalidETag(self):
+        self.client.defaults['HTTP_IF_NONE_MATCH'] = r'"\"'
+        response = self.client.get('/condition/etag/')
+        self.assertFullResponse(response, check_last_modified=False)
+
 
 class ETagProcesing(TestCase):
     def testParsing(self):