diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index ebe8875..85c0750 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -963,9 +963,12 @@ class BaseDatabaseIntrospection(object):
 
     def get_primary_key_column(self, cursor, table_name):
         """
-        Backends can override this to return the column name of the primary key for the given table.
+        Returns the name of the primary key column for the given table
         """
-        raise NotImplementedError
+        for column in self.get_indexes(cursor, table_name).iteritems():
+            if column[1]['primary_key']:
+                return column[0]
+        return None
 
 class BaseDatabaseClient(object):
     """
diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
index ab4eebe..c771337 100644
--- a/django/db/backends/mysql/introspection.py
+++ b/django/db/backends/mysql/introspection.py
@@ -88,15 +88,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                     key_columns.append(match.groups())
         return key_columns
 
-    def get_primary_key_column(self, cursor, table_name):
-        """
-        Returns the name of the primary key column for the given table
-        """
-        for column in self.get_indexes(cursor, table_name).iteritems():
-            if column[1]['primary_key']:
-                return column[0]
-        return None
-
     def get_indexes(self, cursor, table_name):
         """
         Returns a dictionary of fieldname -> infodict for the given table,
diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py
index 0027ec5..dc73ce3 100644
--- a/django/db/backends/postgresql_psycopg2/introspection.py
+++ b/django/db/backends/postgresql_psycopg2/introspection.py
@@ -63,6 +63,23 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
             relations[row[0][0] - 1] = (row[1][0] - 1, row[2])
         return relations
 
+    def get_key_columns(self, cursor, table_name):
+        key_columns = []
+        cursor.execute("""
+            SELECT kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column
+            FROM information_schema.constraint_column_usage ccu
+            LEFT JOIN information_schema.key_column_usage kcu
+                ON ccu.constraint_catalog = kcu.constraint_catalog
+                    AND ccu.constraint_schema = kcu.constraint_schema
+                    AND ccu.constraint_name = kcu.constraint_name
+            LEFT JOIN information_schema.table_constraints tc
+                ON ccu.constraint_catalog = tc.constraint_catalog
+                    AND ccu.constraint_schema = tc.constraint_schema
+                    AND ccu.constraint_name = tc.constraint_name
+            WHERE kcu.table_name = %s AND tc.constraint_type = 'FOREIGN KEY'""" , [table_name])
+        key_columns.extend(cursor.fetchall())
+        return key_columns
+
     def get_indexes(self, cursor, table_name):
         """
         Returns a dictionary of fieldname -> infodict for the given table,
diff --git a/tests/regressiontests/introspection/models.py b/tests/regressiontests/introspection/models.py
index 3b8383e..486133a 100644
--- a/tests/regressiontests/introspection/models.py
+++ b/tests/regressiontests/introspection/models.py
@@ -19,4 +19,4 @@ class Article(models.Model):
         return self.headline
 
     class Meta:
-        ordering = ('headline',)
\ No newline at end of file
+        ordering = ('headline',)
diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py
index fa2b6c5..95c7241 100644
--- a/tests/regressiontests/introspection/tests.py
+++ b/tests/regressiontests/introspection/tests.py
@@ -1,42 +1,12 @@
 from __future__ import absolute_import
 
-from functools import update_wrapper
-
 from django.db import connection
 from django.test import TestCase, skipUnlessDBFeature
 
 from .models import Reporter, Article
 
-#
-# The introspection module is optional, so methods tested here might raise
-# NotImplementedError. This is perfectly acceptable behavior for the backend
-# in question, but the tests need to handle this without failing. Ideally we'd
-# skip these tests, but until #4788 is done we'll just ignore them.
-#
-# The easiest way to accomplish this is to decorate every test case with a
-# wrapper that ignores the exception.
-#
-# The metaclass is just for fun.
-#
-
-def ignore_not_implemented(func):
-    def _inner(*args, **kwargs):
-        try:
-            return func(*args, **kwargs)
-        except NotImplementedError:
-            return None
-    update_wrapper(_inner, func)
-    return _inner
-
-class IgnoreNotimplementedError(type):
-    def __new__(cls, name, bases, attrs):
-        for k,v in attrs.items():
-            if k.startswith('test'):
-                attrs[k] = ignore_not_implemented(v)
-        return type.__new__(cls, name, bases, attrs)
 
 class IntrospectionTests(TestCase):
-    __metaclass__ = IgnoreNotimplementedError
 
     def test_table_names(self):
         tl = connection.introspection.table_names()
@@ -106,6 +76,7 @@ class IntrospectionTests(TestCase):
             # That's {field_index: (field_index_other_table, other_table)}
             self.assertEqual(relations, {3: (0, Reporter._meta.db_table)})
 
+    @skipUnlessDBFeature('can_introspect_foreign_keys')
     def test_get_key_columns(self):
         cursor = connection.cursor()
         key_columns = connection.introspection.get_key_columns(cursor, Article._meta.db_table)
