prefetch_definitions aren't preserved across an FK reverse relationship
Given these models:
class User(Model):
pass
class UserThing(Model):
user = ForiegnKey(User, related_name='things')
objects = PrefetchManager(
# prefetches here...
)
I'd like to be able to be able to do user.things.prefetch('stuff'). PrefetchManagerMixin does set use_for_related_fields, so user.things is a PrefetchManager, but it doesn't have any prefetch_definitions. This is because Django only uses the class of the manager to create its RelatedManager. See ForeignRelatedObjectsDescriptor.related_manager_cls.
One way to solve this issue would be to have a class factory that returned PrefetchManager classes with prefetch_definitions already set. If this isn't feasible, a way to reduce the impact would be to allow PrefetchQuerySet.prefetch to take a Prefetcher. This way you could use the actual Prefetcher instance instead of a name when the table of names isn't available.
If either of these solutions sound interesting, let me know and I can write a patch.
Note that I haven't tried but this should do the trick (if django works as you describe)
class User(Model):
pass
class UserThingPrefetchManager(PrefetchManager):
prefetch_definitions = dict(
# prefetches here...
)
class UserThing(Model):
user = ForiegnKey(User, related_name='things')
objects = UserThingPrefetchManager()
On second thought you have to subclass the mixin as the initializer in PrefetchManager will just empty the prefetch_definitions. Eg:
class UserThingPrefetchManager(PrefetchManagerMixin):
prefetch_definitions = dict(
# prefetches here...
)
But a class factory would be more useful (it's not obvious that you need a class definition like that). However, that presents its own challenge as the class would be non-pickleable if it's not defined at module level (you can always patch the module with the anonymous class that the factory would return by looking at stackframes but that's ugly).
What do you think ?