﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
28806	Mechanism of fetching related objects violates READ COMMITTED assumption of Django ORM	Aaron Tan	nobody	"Found here: https://github.com/django/django/blob/master/django/db/models/fields/related_descriptors.py#L141.
{{{
def get_object(self, instance):
        qs = self.get_queryset(instance=instance)
        # Assuming the database enforces foreign keys, this won't fail.
        return qs.get(self.field.get_reverse_related_filter(instance))
}}}


The comment in that function states: `# Assuming the database enforces foreign keys, this won't fail.`, but it's not the case. I will illustrate with a use case we met:

Suppose we have 2 concurrent transactions A and B talking to the same Postgresql backend, and we have two models:
{{{
class Foo:
    pass

class Bar:
    fk = ForeignKey(Foo, on_delete=models.SET_NULL)
}}}
populated by objects
{{{
foo = Foo()
foo.save()
bar = Bar(fk=foo)
bar.save()
}}}
Transaction A runs
{{{
bar = Bar.objects.get(pk=<bar's pk>)
}}}
Then transaction B runs
{{{
Foo.objects.get(pk=<foo's pk>).delete()
}}}
If READ COMMITTED is assumed by Django, transaction A will see the db snapshot with `foo` deleted. But if transaction A subsequently did
{{{
bar.fk #Access foreign key field `fk` for the first time
}}}

Because the `get_object` method linked does not catch `ObjectDoesNotExist` exception tossed by `get`, the last `bar.fk` will raise `ObjectDoesNotExist`, thus contradicts the assumption

> the database enforces foreign keys, this won't fail.

We currently manually catch `ObjectDoesNotExist` but that makes code ugly, I suggest instantiate the related field to `None` in that case, instead of raising exception."	Bug	closed	Database layer (models, ORM)	dev	Normal	wontfix	database, read-committed, concurrency control		Unreviewed	0	0	0	0	0	0
