Index: django/db/models/sql/where.py
===================================================================
--- django/db/models/sql/where.py	(revision 9817)
+++ django/db/models/sql/where.py	(working copy)
@@ -174,9 +174,9 @@
                     params)
         elif lookup_type in ('range', 'year'):
             return ('%s BETWEEN %%s and %%s' % field_sql, params)
-        elif lookup_type in ('month', 'day'):
-            return ('%s = %%s' % connection.ops.date_extract_sql(lookup_type,
-                    field_sql), params)
+        elif lookup_type in ('month', 'day', 'week_day'):
+            return ('%s = %%s' % connection.ops.date_extract_sql(lookup_type, field_sql),
+                    params)
         elif lookup_type == 'isnull':
             return ('%s IS %sNULL' % (field_sql,
                 (not value_annot and 'NOT ' or '')), ())
Index: django/db/models/sql/constants.py
===================================================================
--- django/db/models/sql/constants.py	(revision 9817)
+++ django/db/models/sql/constants.py	(working copy)
@@ -4,7 +4,7 @@
 QUERY_TERMS = dict([(x, None) for x in (
     'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in',
     'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year',
-    'month', 'day', 'isnull', 'search', 'regex', 'iregex',
+    'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex',
     )])
 
 # Size of each "chunk" for get_iterator calls.
Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 9817)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -201,7 +201,7 @@
             sql, params = value.as_sql()
             return QueryWrapper(('(%s)' % sql), params)
 
-        if lookup_type in ('regex', 'iregex', 'month', 'day', 'search'):
+        if lookup_type in ('regex', 'iregex', 'month', 'day', 'week_day', 'search'):
             return [value]
         elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
             return [self.get_db_prep_value(value)]
@@ -492,7 +492,7 @@
     def get_db_prep_lookup(self, lookup_type, value):
         # For "__month" and "__day" lookups, convert the value to a string so
         # the database backend always sees a consistent type.
-        if lookup_type in ('month', 'day'):
+        if lookup_type in ('month', 'day', 'week_day'):
             return [force_unicode(value)]
         return super(DateField, self).get_db_prep_lookup(lookup_type, value)
 
Index: django/db/backends/postgresql/operations.py
===================================================================
--- django/db/backends/postgresql/operations.py	(revision 9817)
+++ django/db/backends/postgresql/operations.py	(working copy)
@@ -26,7 +26,12 @@
 
     def date_extract_sql(self, lookup_type, field_name):
         # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
-        return "EXTRACT('%s' FROM %s)" % (lookup_type, field_name)
+        if lookup_type == 'week_day':
+            # Using EXTRACT(), PostgreSQL days are indexed as Sunday=0, Saturday=6.
+            # If we instead us TO_CHAR, they're indexed with Sunday=1, Saturday=7
+            return "TO_CHAR(%s, 'D')" % field_name
+        else:
+            return "EXTRACT('%s' FROM %s)" % (lookup_type, field_name)
 
     def date_trunc_sql(self, lookup_type, field_name):
         # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
Index: django/db/backends/sqlite3/base.py
===================================================================
--- django/db/backends/sqlite3/base.py	(revision 9817)
+++ django/db/backends/sqlite3/base.py	(working copy)
@@ -207,7 +207,10 @@
         dt = util.typecast_timestamp(dt)
     except (ValueError, TypeError):
         return None
-    return unicode(getattr(dt, lookup_type))
+    if lookup_type == 'week_day':
+        return unicode((dt.isoweekday() % 7) + 1)
+    else:
+        return unicode(getattr(dt, lookup_type))
 
 def _sqlite_date_trunc(lookup_type, dt):
     try:
Index: django/db/backends/mysql/base.py
===================================================================
--- django/db/backends/mysql/base.py	(revision 9817)
+++ django/db/backends/mysql/base.py	(working copy)
@@ -116,7 +116,12 @@
 class DatabaseOperations(BaseDatabaseOperations):
     def date_extract_sql(self, lookup_type, field_name):
         # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
-        return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
+        if lookup_type == 'week_day':
+            # DAYOFWEEK() returns an integer, 1-7, Sunday=1.
+            # Note: WEEKDAY() returns 0-6, Monday=0.
+            return "DAYOFWEEK(%s)" % field_name
+        else:
+            return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
 
     def date_trunc_sql(self, lookup_type, field_name):
         fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
Index: django/db/backends/oracle/base.py
===================================================================
--- django/db/backends/oracle/base.py	(revision 9817)
+++ django/db/backends/oracle/base.py	(working copy)
@@ -72,7 +72,11 @@
 
     def date_extract_sql(self, lookup_type, field_name):
         # http://download-east.oracle.com/docs/cd/B10501_01/server.920/a96540/functions42a.htm#1017163
-        return "EXTRACT(%s FROM %s)" % (lookup_type, field_name)
+        if lookup_type == 'week_day':
+            # TO_CHAR(field, 'D') returns an integer from 1-7, where 1=Sunday.
+            return "TO_CHAR(%s, 'D')" % field_name
+        else:
+            return "EXTRACT(%s FROM %s)" % (lookup_type, field_name)
 
     def date_trunc_sql(self, lookup_type, field_name):
         # Oracle uses TRUNC() for both dates and numbers.
@@ -268,9 +272,11 @@
             self.connection = Database.connect(conn_string, **self.options)
             cursor = FormatStylePlaceholderCursor(self.connection)
             # Set oracle date to ansi date format.  This only needs to execute
-            # once when we create a new connection.
+            # once when we create a new connection. We also set the Territory
+            # to 'AMERICA' which forces Sunday to evaluate to a '1' in TO_CHAR().
             cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' "
-                           "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")
+                           "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF' "
+                           "NLS_TERRITORY = 'AMERICA'")
             try:
                 self.oracle_version = int(self.connection.version.split('.')[0])
                 # There's no way for the DatabaseOperations class to know the
Index: tests/modeltests/basic/models.py
===================================================================
--- tests/modeltests/basic/models.py	(revision 9817)
+++ tests/modeltests/basic/models.py	(working copy)
@@ -74,6 +74,8 @@
 <Article: Area woman programs in Python>
 >>> Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
 <Article: Area woman programs in Python>
+>>> Article.objects.get(pub_date__week_day=5)
+<Article: Area woman programs in Python>
 
 # The "__exact" lookup type can be omitted, as a shortcut.
 >>> Article.objects.get(id=1)
@@ -88,6 +90,11 @@
 >>> Article.objects.filter(pub_date__year=2005, pub_date__month=7)
 [<Article: Area woman programs in Python>]
 
+>>> Article.objects.filter(pub_date__week_day=5)
+[<Article: Area woman programs in Python>]
+>>> Article.objects.filter(pub_date__week_day=6)
+[]
+
 # Django raises an Article.DoesNotExist exception for get() if the parameters
 # don't match any object.
 >>> Article.objects.get(id__exact=2)
@@ -100,6 +107,11 @@
     ...
 DoesNotExist: Article matching query does not exist.
 
+>>> Article.objects.get(pub_date__week_day=6)
+Traceback (most recent call last):
+    ...
+DoesNotExist: Article matching query does not exist.
+
 # Lookup by a primary key is the most common case, so Django provides a
 # shortcut for primary-key exact lookups.
 # The following is identical to articles.get(id=1).
Index: docs/ref/models/querysets.txt
===================================================================
--- docs/ref/models/querysets.txt	(revision 9817)
+++ docs/ref/models/querysets.txt	(working copy)
@@ -1344,6 +1344,25 @@
 Note this will match any record with a pub_date on the third day of the month,
 such as January 3, July 3, etc.
 
+week_day
+~~~~~~~~
+
+For date/datetime fields, a 'day of the week' match.
+
+Example::
+
+    Entry.objects.filter(pub_date__week_day=2)
+
+SQL equivalent::
+
+    SELECT ... WHERE EXTRACT('dow' FROM pub_date) = '2';
+
+(The exact SQL syntax varies for each database engine.)
+
+Note this will match any record with a pub_date that falls on a Monday (day 2
+of the week), regardless of the month or year in which it occurs. Week days
+are indexed with day 1 being Sunday and day 7 being Saturday.
+
 isnull
 ~~~~~~
 
