﻿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
30083	Model instance state not correctly set when initializing a model with Model.from_db()	Sebastiaan ten Pas	Nasir Hussain	"When loading a model instance through `from_db`, it first makes a new instance and after sets the state:

{{{#!python
    @classmethod
    def from_db(cls, db, field_names, values):
        if len(values) != len(cls._meta.concrete_fields):
            values_iter = iter(values)
            values = [
                next(values_iter) if f.attname in field_names else DEFERRED
                for f in cls._meta.concrete_fields
            ]
        new = cls(*values)
        new._state.adding = False
        new._state.db = db
        return new
}}}

This means that during the class initialization, the model instance state is equal to `_state.adding = True` and `_state.db = None`. This can cause troubles with related queries in the pre-/post-init methods. For example:

{{{#!python
class Parent(models.Model):
    pass


class Child(models.Model):
    parent = models.ForeignKey(Parent)


def foo(instance, **kwargs)
    print(instance._state.adding)
    print(instance._state.db)

    # It could be that we initialize the model while it does not exist in the
    # database, so we check whether `instance.parent` exists first.
    if getattr(instance, 'parent', None):
        # Since we try to access instance.parent, it passes the `instance`
        # as hint to the router, but `instance._state.db` is `None`, so it defaults
        # to the `DEFAULT_DB_ALIAS`.
        assert instance._state.db == instance.parent._state.db


signals.post_init.connect(foo, sender=Child)
}}}

Trying to fetch an instance of `Child`, will now return:

{{{#!python
>>> child = Child.objects.using('second').get(pk=1)
True
None
AssertionError
}}}

The current behavior indicates that one should never do related queries in the `pre_init` or `post_init` hooks, because it cannot be guaranteed that the related queries are done on the same database you're retrieving the instance from. Currently there's also no way of getting to know the on which database the query was done for in the `pre_init` and `post_init` hooks because the state is set after those signals are fired.

One related issue is #18532, which is only talking about the `_state.adding` flag. There's a suggested solution over there, but I'm not sure if that's the best way to go. I think there should be at least a note in the Django documentation at the `pre_init` and `post_init` hooks saying that related queries should be avoided, because it cannot be guaranteed that they will be run on the same database you're getting the instance from."	Bug	closed	Database layer (models, ORM)	2.1	Normal	wontfix			Accepted	1	0	0	0	0	0
