--- a/django/contrib/contenttypes/generic.py
+++ b/django/contrib/contenttypes/generic.py
@@ -253,6 +253,8 @@ def create_generic_related_manager(superclass):
 
         def add(self, *objs):
             for obj in objs:
+                if not isinstance(obj, self.model):
+                    raise TypeError, "'%s' instance expected" % self.model._meta.object_name
                 setattr(obj, self.content_type_field_name, self.content_type)
                 setattr(obj, self.object_id_field_name, self.pk_val)
                 obj.save()
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 146a1ae..af88959 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -20,6 +20,14 @@ RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
 
 pending_lookups = {}
 
+_Model = None
+def get_model_class():
+    global _Model
+    if _Model is None:
+        from django.db.models.base import Model
+        _Model = Model
+    return _Model
+
 def add_lazy_relation(cls, field, relation, operation):
     """
     Adds a lookup on ``cls`` when a related field is defined using a string,
@@ -302,6 +310,8 @@ class ForeignRelatedObjectsDescriptor(object):
 
             def add(self, *objs):
                 for obj in objs:
+                    if not isinstance(obj, self.model):
+                        raise TypeError, "'%s' instance expected" % self.model._meta.object_name
                     setattr(obj, rel_field.name, instance)
                     obj.save()
             add.alters_data = True
@@ -438,6 +448,8 @@ def create_many_related_manager(superclass, through=False):
                 for obj in objs:
                     if isinstance(obj, self.model):
                         new_ids.add(obj._get_pk_val())
+                    elif isinstance(obj, get_model_class()):
+                        raise TypeError, "'%s' instance expected" % self.model._meta.object_name
                     else:
                         new_ids.add(obj)
                 # Add the newly created or already existing objects to the join table.
diff --git a/tests/modeltests/many_to_many/models.py b/tests/modeltests/many_to_many/models.py
index cc34c86..21b4e82 100644
--- a/tests/modeltests/many_to_many/models.py
+++ b/tests/modeltests/many_to_many/models.py
@@ -61,6 +61,12 @@ ValueError: 'Article' instance needs to have a primary key value before a many-t
 # Adding a second time is OK
 >>> a2.publications.add(p3)
 
+# Adding an object of the wrong type raises TypeError
+>>> a2.publications.add(a1)
+Traceback (most recent call last):
+...
+TypeError: 'Publication' instance expected
+
 # Add a Publication directly via publications.add by using keyword arguments.
 >>> new_publication = a2.publications.create(title='Highlights for Children')
 
diff --git a/tests/modeltests/many_to_one/models.py b/tests/modeltests/many_to_one/models.py
index 1972ac7..8093e73 100644
--- a/tests/modeltests/many_to_one/models.py
+++ b/tests/modeltests/many_to_one/models.py
@@ -72,6 +72,13 @@ __test__ = {'API_TESTS':"""
 >>> r2.article_set.add(new_article2)
 >>> new_article2.reporter.id
 2
+
+# Adding an object of the wrong type raises TypeError
+>>> r.article_set.add(r2)
+Traceback (most recent call last):
+...
+TypeError: 'Article' instance expected
+
 >>> r.article_set.all()
 [<Article: John's second story>, <Article: This is a test>]
 >>> r2.article_set.all()
