python - Schema agnostic model design -


it time question on design , performance.

say have 3 django models:

class student(model):   classroom = foreignkey('classroom')   # student info  class classroom(model):   teacher = foreignkey('teacher')   # classroom info  class teacher(model):   # teacher info 

i want make sure view has nice way access students teacher has. this, might make sense have method defined on teacher model

def get_students(self):    # code 

now, there few ways this. 1 of priorities keep each model relatively agnostic overall database schema. result, don't following solution:

def get_students(self):   return student.objects.filter(classroom__teacher=self) 

this solution relies on students being related teachers via classroom; if change structure (maybe students need related teachers directly, rather through classroom), have change get_students method. if have bunch of models , relate each other through these nested relationships, changing schema means hunting down such filter queries. in particular case, have number of models exist in different applications , project getting quite big, taking approach means inviting sorts of opportunities me miss , create bug. if tests good, have spend lot of time looking queries.

a solution seems more elegant me have student manager defines for_teacher method:

class studentmanager(manager):   def for_teacher(self, teacher):     return self.filter(classroom__teacher=teacher) 

now, get_students method can this:

def get_students(self):   return students.objects.for_teacher(self) 

with approach, i've abstracted things teacher doesn't know how related student (namely, through classroom). knows is related students somehow. of course, if change schema, have change studentmanager. however, if again imagine project many models related other models through different models, method offers way concentrate schema-dependent calls in 1 place (the managers). saves me having hunt down queries in sorts of models (and views, perhaps).

the question is, sane approach? if not, preferred way handle this?

a corollary:

as mentioned above, project has bunch of models in bunch of apps , need know each other somehow. have added issue: if teacher contains get_students method , student has get_teacher method, run cyclic module dependencies. potential solution new problem version of get_students (get_teacher):

def get_students(self):   student.models import student   return student.objects.for_teacher(self) 

i come world imports put @ top of program, seems little strange me. reasonable approach? there performance considerations when doing dynamic imports this? python cache student import in get_students method happens once?

thanks in advance!

certainly seems fine idea centralize schema-dependent operations in 1 place. however, don't see advantage doing in managers instead of models propose.

this method offers way concentrate schema-dependent calls in 1 place (the managers)

but managers aren't in 1 place, there 1 each relevant model, , put in exact same place - models.py. in example there's no advantage, since in both cases have change 1 method if schema changed.

don't me wrong, managers great, , studentmanager.for_teacher() might make more sense teacher.get_students() based on needs , access patterns. don't see advantage encapsulation point of view.

as imports, it's common , accepted import module inside function if that's necessary avoid circular import, though it's less pythonic. pep 8 advises against it, doesn't why. cited reason (in experience) makes harder track module's dependencies when imports spread around file. performance not important consideration here since python indeed cache imported module.

it's true circular imports sign more serious going wrong. however, in django it's not uncommon , not troublesome in , of itself.


Comments

Popular posts from this blog

node.js - Using Node without global install -

How to access a php class file from PHPFox framework into javascript code written in simple HTML file? -

java - Null response to php query in android, even though php works properly -