Index: django/db/models/base.py
===================================================================
--- django/db/models/base.py	(revision 12492)
+++ django/db/models/base.py	(working copy)
@@ -638,6 +638,14 @@
         return getattr(self, cachename)
 
     def prepare_database_save(self, unused):
+        if self.pk is None:
+            # This is reached if this instance is missing a primary key value
+            # but is passed as a parameter to a queryset's update() method,
+            # which needs some value to use as a foreign key.
+            raise ValueError('Cannot assign the instance "%r" to a foreign key'
+                ' field, because its primary key is not available.'
+                ' (For autonumbered keys, the instance would need to be saved'
+                ' first.)' % self)
         return self.pk
 
     def clean(self):
Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 12492)
+++ django/db/models/fields/related.py	(working copy)
@@ -330,6 +330,20 @@
             val = getattr(value, self.field.rel.get_related_field().attname)
         except AttributeError:
             val = None
+        if val is None and value is not None and self.field.null:
+            # Raise an error if we're assigning an instance but can't get a
+            # relational key to use for that instance. This typically happens
+            # when a new instance's autonumbered primary key hasn't been
+            # assigned because it hasn't been saved yet.
+            # This exception is only thrown for nullable foreign keys.
+            # Non-nullable foreign keys will already throw an exception
+            # (albeit later, at save time, and with a less helpful message)
+            # so we retain their previous behavior.
+            raise ValueError('Cannot assign the instance "%r" to "%s.%s",'
+                ' because a relational key for the instance is not available.'
+                ' (For autonumbered keys, the instance may need to be saved'
+                ' first.)' %
+                (value, instance._meta.object_name, self.field.name))
         setattr(instance, self.field.attname, val)
 
         # Since we already know what the related object is, seed the related
Index: tests/regressiontests/model_regress/tests.py
===================================================================
--- tests/regressiontests/model_regress/tests.py	(revision 12492)
+++ tests/regressiontests/model_regress/tests.py	(working copy)
@@ -1,4 +1,5 @@
-from models import Worker
+from models import Worker, Site, ArticleWithOptionalSite
+from django.core.exceptions import ObjectDoesNotExist
 from django.test import TestCase
 
 class RelatedModelOrderedLookupTest(TestCase):
@@ -14,3 +15,47 @@
 
     def test_related_lte_lookup(self):
         Worker.objects.filter(department__lte=0)
+
+class AssignmentWithMissingForeignKeyTest(TestCase):
+    """
+    Regression test for #11811: setting a nullable foreign key to a model
+    instance with a null pk (i.e. an unsaved instance) should raise an
+    exception.
+    """
+    def test_attr_assignment(self):
+        s = Site(name='My Unsaved Site')
+        a = ArticleWithOptionalSite(id=1,
+            text='I will try to specify that site')
+        def error_line():
+            a.site = s
+        self.assertRaises(ValueError, error_line)
+        # ValueError: Cannot assign the instance "<Site: My Unsaved Site>" to "ArticleWithOptionalSite.site", because a relational key for the instance is not available. (For autonumbered keys, the instance may need to be saved first.)
+
+    def test_model_initializer(self):
+        s = Site(name='My Unsaved Site')
+        def error_line():
+            a = ArticleWithOptionalSite(id=2,
+                text='I will also try to specify that site', site=s)
+        self.assertRaises(ValueError, error_line)
+        # ValueError: Cannot assign the instance "<Site: My Unsaved Site>" to "ArticleWithOptionalSite.site", because a relational key for the instance is not available. (For autonumbered keys, the instance may need to be saved first.)
+        self.assertRaises(ObjectDoesNotExist,
+            lambda: ArticleWithOptionalSite.objects.get(id=2))
+    
+    def test_manager_create(self):
+        s = Site(name='My Unsaved Site')
+        def error_line():
+            a = ArticleWithOptionalSite.objects.create(id=3,
+                text='Never mind, I will try to specify that site', site=s)
+        self.assertRaises(ValueError, error_line)
+        # ValueError: Cannot assign the instance "<Site: My Unsaved Site>" to "ArticleWithOptionalSite.site", because a relational key for the instance is not available. (For autonumbered keys, the instance may need to be saved first.)
+        self.assertRaises(ObjectDoesNotExist,
+            lambda: ArticleWithOptionalSite.objects.get(id=3))
+    
+    def test_queryset_update(self):
+        s = Site(name='My Unsaved Site')
+        a = ArticleWithOptionalSite.objects.create(id=4,
+            text='Not specifying a site')
+        def error_line():
+            ArticleWithOptionalSite.objects.filter(id=4).update(site=s)
+        self.assertRaises(ValueError, error_line)
+        # ValueError: Cannot assign the instance "<Site: My Unsaved Site>" to a foreign key field, because its primary key is not available. (For autonumbered keys, the instance would need to be saved first.)
Index: tests/regressiontests/model_regress/models.py
===================================================================
--- tests/regressiontests/model_regress/models.py	(revision 12492)
+++ tests/regressiontests/model_regress/models.py	(working copy)
@@ -50,6 +50,16 @@
     def __unicode__(self):
         return self.name
 
+class Site(models.Model):
+    name = models.CharField(max_length=200)
+
+    def __unicode__(self):
+        return self.name
+
+class ArticleWithOptionalSite(models.Model):
+    text = models.TextField()
+    site = models.ForeignKey(Site, null=True)
+
 class BrokenUnicodeMethod(models.Model):
     name = models.CharField(max_length=7)
 
