diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 61fd2be..2863a50 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1045,11 +1045,52 @@ class Query(object):
         if not parts:
             raise FieldError("Cannot parse keyword query %r" % arg)
 
-        # Work out the lookup type and remove it from 'parts', if necessary.
-        if len(parts) == 1 or parts[-1] not in self.query_terms:
-            lookup_type = 'exact'
-        else:
-            lookup_type = parts.pop()
+        lookup_type = "exact"
+        model = self.model
+        # walk the relations and figure out the lookup type
+        if len(parts) > 1 and arg not in self.aggregates:
+            for idx, part in enumerate(parts):
+                try:
+                    if part == "pk":
+                        field = model._meta.pk
+                    else:
+                        # Try to retrieve one of the model's fields from the
+                        # given part.
+                        try:
+                            field, _, _, _ = model._meta.get_field_by_name(part)
+                        except FieldDoesNotExist:
+                            # The first attempt failed. Let's check if it's
+                            # a foreignkey.
+                            if len(part) > 3 and part[-3:] == '_id':
+                                field, _, _, _ = model._meta.get_field_by_name(part[:-3])
+                            else:
+                                # OK, so the field really doesn't exist
+                                raise
+                        if hasattr(field, "model") and field.model != model:
+                            model = field.model
+                            continue
+                        if hasattr(field, "field"):
+                            # RelatedObjects
+                            field = field.field
+                    if field.rel is not None:
+                        model = field.rel.to
+                        continue
+                    # If we reach here we are no longer traversing relations
+                    if idx < len(parts) - 1 and parts[-1] in self.query_terms:
+                        lookup_type = parts.pop()
+                    break
+                except FieldDoesNotExist:
+                    if part in self.aggregates and parts[-1] in self.query_terms:
+                        lookup_type = parts.pop()
+                        break
+                    # if we're not on the last part something is wrong
+                    if idx != len(parts) - 1:
+                        # We can't handle this - fall through
+                        if parts[-1] in self.query_terms:
+                            lookup_type = parts.pop()
+                        break
+                    lookup_type = parts.pop()
+                    break
 
         # By default, this is a WHERE clause. If an aggregate is referenced
         # in the value, the filter will be promoted to a HAVING
diff --git a/tests/modeltests/lookup_collision/__init__.py b/tests/modeltests/lookup_collision/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modeltests/lookup_collision/models.py b/tests/modeltests/lookup_collision/models.py
new file mode 100644
index 0000000..e8ed05a
--- /dev/null
+++ b/tests/modeltests/lookup_collision/models.py
@@ -0,0 +1,24 @@
+from django.db import models, DEFAULT_DB_ALIAS, connection
+from django.conf import settings
+
+class RepeatingEvent(models.Model):
+    name = models.CharField(max_length=100)
+    week_day = models.IntegerField()
+    class Meta:
+        ordering = ('week_day', 'name', )
+
+class Appointment(models.Model):
+    name = models.CharField(max_length=100)
+    day = models.DateField()
+    repeating = models.ForeignKey(RepeatingEvent)
+    class Meta:
+        ordering = ('day', 'name', )
+
+class Calendar(models.Model):
+    name = models.CharField(max_length=100)
+    appointments = models.ManyToManyField(Appointment)
+    class Meta:
+        ordering = ('name',)
+
+    def __unicode__(self):
+        return self.name
diff --git a/tests/modeltests/lookup_collision/tests.py b/tests/modeltests/lookup_collision/tests.py
new file mode 100644
index 0000000..0a87730
--- /dev/null
+++ b/tests/modeltests/lookup_collision/tests.py
@@ -0,0 +1,44 @@
+from datetime import datetime
+from django.test import TestCase
+from models import RepeatingEvent, Appointment, Calendar
+
+
+class LookupCollisionTests(TestCase):
+    """Test for collisions between lookup type names and field names"""
+
+    def setUp(self):
+        # Create a RepeatingEvent
+        self.rep1 = RepeatingEvent(name="Every Thursday", week_day=5)
+        self.rep1.save()
+        # Create an Appointment
+        self.ap1 = Appointment(name="Today and every thursday", day=datetime(2011, 6, 9), repeating=self.rep1)
+        self.ap1.save()
+        # Create a Calendar
+        self.cal = Calendar(name="My Calendar")
+        self.cal.save()
+        self.cal.appointments = [self.ap1, ]
+        self.cal.save()
+
+    def test_query_simple(self):
+        """Test simple queries with colliding names without traversing relations"""
+        self.assertTrue(RepeatingEvent.objects.filter(week_day=5).exists())
+        self.assertTrue(Appointment.objects.filter(day=datetime(2011, 6, 9)).exists())
+
+    def test_query_related(self):
+        """Test queries through related fields with colliding field names"""
+        self.assertTrue(Appointment.objects.filter(repeating__week_day=5).exists())
+
+        self.assertTrue(Calendar.objects.filter(appointments__day=datetime(2011, 6, 9)).exists())
+        self.assertTrue(Calendar.objects.filter(appointments__repeating__week_day=5).exists())
+
+    def test_query_related_with_lookup(self):
+        """Test queries through related fields with colliding names with explicit lookup types"""
+        self.assertTrue(RepeatingEvent.objects.filter(week_day__exact=5).exists())
+
+        self.assertTrue(Appointment.objects.filter(day__exact=datetime(2011, 6, 9)).exists())
+        self.assertTrue(Appointment.objects.filter(day__week_day=5).exists())
+        self.assertTrue(Appointment.objects.filter(repeating__week_day__exact=5).exists())
+
+        self.assertTrue(Calendar.objects.filter(appointments__day__exact=datetime(2011, 6, 9)).exists())
+        self.assertTrue(Calendar.objects.filter(appointments__day__week_day=5).exists())
+        self.assertTrue(Calendar.objects.filter(appointments__repeating__week_day__exact=5).exists())
