Ticket #11811: 11811-patch-rev-3.diff

File 11811-patch-rev-3.diff, 6.0 KB (added by ashearer, 14 years ago)

Patch

  • django/db/models/base.py

     
    638638        return getattr(self, cachename)
    639639
    640640    def prepare_database_save(self, unused):
     641        if self.pk is None:
     642            # This is reached if this instance is missing a primary key value
     643            # but is passed as a parameter to a queryset's update() method,
     644            # which needs some value to use as a foreign key.
     645            raise ValueError('Cannot assign the instance "%r" to a foreign key'
     646                ' field, because its primary key is not available.'
     647                ' (For autonumbered keys, the instance would need to be saved'
     648                ' first.)' % self)
    641649        return self.pk
    642650
    643651    def clean(self):
  • django/db/models/fields/related.py

     
    330330            val = getattr(value, self.field.rel.get_related_field().attname)
    331331        except AttributeError:
    332332            val = None
     333        if val is None and value is not None and self.field.null:
     334            # Raise an error if we're assigning an instance but can't get a
     335            # relational key to use for that instance. This typically happens
     336            # when a new instance's autonumbered primary key hasn't been
     337            # assigned because it hasn't been saved yet.
     338            # This exception is only thrown for nullable foreign keys.
     339            # Non-nullable foreign keys will already throw an exception
     340            # (albeit later, at save time, and with a less helpful message)
     341            # so we retain their previous behavior.
     342            raise ValueError('Cannot assign the instance "%r" to "%s.%s",'
     343                ' because a relational key for the instance is not available.'
     344                ' (For autonumbered keys, the instance may need to be saved'
     345                ' first.)' %
     346                (value, instance._meta.object_name, self.field.name))
    333347        setattr(instance, self.field.attname, val)
    334348
    335349        # Since we already know what the related object is, seed the related
  • tests/regressiontests/model_regress/tests.py

     
    1 from models import Worker
     1from models import Worker, Site, ArticleWithOptionalSite
     2from django.core.exceptions import ObjectDoesNotExist
    23from django.test import TestCase
    34
    45class RelatedModelOrderedLookupTest(TestCase):
     
    1415
    1516    def test_related_lte_lookup(self):
    1617        Worker.objects.filter(department__lte=0)
     18
     19class AssignmentWithMissingForeignKeyTest(TestCase):
     20    """
     21    Regression test for #11811: setting a nullable foreign key to a model
     22    instance with a null pk (i.e. an unsaved instance) should raise an
     23    exception.
     24    """
     25    def test_attr_assignment(self):
     26        s = Site(name='My Unsaved Site')
     27        a = ArticleWithOptionalSite(id=1,
     28            text='I will try to specify that site')
     29        def error_line():
     30            a.site = s
     31        self.assertRaises(ValueError, error_line)
     32        # 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.)
     33
     34    def test_model_initializer(self):
     35        s = Site(name='My Unsaved Site')
     36        def error_line():
     37            a = ArticleWithOptionalSite(id=2,
     38                text='I will also try to specify that site', site=s)
     39        self.assertRaises(ValueError, error_line)
     40        # 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.)
     41        self.assertRaises(ObjectDoesNotExist,
     42            lambda: ArticleWithOptionalSite.objects.get(id=2))
     43   
     44    def test_manager_create(self):
     45        s = Site(name='My Unsaved Site')
     46        def error_line():
     47            a = ArticleWithOptionalSite.objects.create(id=3,
     48                text='Never mind, I will try to specify that site', site=s)
     49        self.assertRaises(ValueError, error_line)
     50        # 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.)
     51        self.assertRaises(ObjectDoesNotExist,
     52            lambda: ArticleWithOptionalSite.objects.get(id=3))
     53   
     54    def test_queryset_update(self):
     55        s = Site(name='My Unsaved Site')
     56        a = ArticleWithOptionalSite.objects.create(id=4,
     57            text='Not specifying a site')
     58        def error_line():
     59            ArticleWithOptionalSite.objects.filter(id=4).update(site=s)
     60        self.assertRaises(ValueError, error_line)
     61        # 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.)
  • tests/regressiontests/model_regress/models.py

     
    5050    def __unicode__(self):
    5151        return self.name
    5252
     53class Site(models.Model):
     54    name = models.CharField(max_length=200)
     55
     56    def __unicode__(self):
     57        return self.name
     58
     59class ArticleWithOptionalSite(models.Model):
     60    text = models.TextField()
     61    site = models.ForeignKey(Site, null=True)
     62
    5363class BrokenUnicodeMethod(models.Model):
    5464    name = models.CharField(max_length=7)
    5565
Back to Top