Задать вопрос

Тел: +7 965 3737 888





Manager introspecting attached model

<p><a href="http://www.b-list.org/weblog/2008/feb/25/managers/#c63422">A comment on a recent blog entry of mine</a> asked about a setup where one model has foreign keys pointing at it from several others, and how to write a manager which could attach to any of those models and query seamlessly on the relation regardless of what it's named.</p>
<p>This is a simple example of how to do it: in this case, both Movie and Restaurant have foreign keys to Review, albeit under different names. However, they both use ReviewedObjectManager to provide a method for querying objects whose review assigned a certain rating; this works because an instance of ReviewedObjectManager "knows" what model it's attached to, and can introspect that model, using <a href="http://www.b-list.org/weblog/2007/nov/04/working-models/">Django's model-introspection API</a>, to find out the correct name to use for the relation, and then use that to perform the query.</p>
<p>Using model introspection in this fashion is something of an advanced topic, but is extremely useful for writing flexible, reusable code.</p>
<p><strong>Also</strong>, note that the introspection cannot be done in the manager's __init__() method -- at that point, self.model is still None (it won't be filled in with the correct model until a bit later) -- so it's necessary to come up with some way to defer the introspection. In this case, I'm doing it in a method that's called when the relation name is first needed, and which caches the result in an attribute.</p>

Вопрос полезен? Да0/Нет0

Ответы (1):

Ответ полезен? Да0/Нет0

Another place to grab _review_field would be in contribute_to_class -- that's the method called when the model metaclass adds the manager to the class. Just be sure to call the superclass method!

In fact, I'd say that contribute_to_class would be the correct place to do this initialization since contribute_to_class is the "official" mechanism by which "things attached to models" get to poke at the model.