Models question

They can go as deep as you need them to.

If you have the ForeignKeys defined as having the same name as the target class, and you have an instance of School named school, then the query for all Student in that school would be Student.objects.filter(schoolclass__team__departmening__school=school)

This is a “best practice”, but not the only viable option. There are other ways, but whether or not they’re “better” is both subjective and dependant upon the operational characteristics of the data. (These characteristics to consider include the sizes of the individual levels, the frequency of updates to the data, what the distribution of those updates are among different insert, updates, and deletions of each of the levels, and what the common operations are - what the common queries are expected to be relative to the uncommon queries - and what the relative number of queries are going to be performed to the number of updates.)

Another option to consider would be one of the hierarchical representations for this data. This structure is a hierarchy, with the characteristic of the number of levels being fixed and given. (See Some modelling advice - #12 by KenWhitesell for more thoughts on this.) If I were to make a guess as to some of the answers above, I could see where either a Nested Set Tree or a Materialized Path Tree could be quite useful for this.