django-polymorphic
django-polymorphic copied to clipboard
hacks for getting around the `select_related` issue from parent on inherited models to avoid n+1 queries?
So I've read this issue extensively and tried some things out which don't work -- https://github.com/django-polymorphic/django-polymorphic/issues/198
So I'm trying to see if I can come to a middle ground where maybe I don't get the free select_related
query but can add a prefetch_related
and avoid n+1s. I have some models defined like this
class Message(PolymorphicModel):
body = models.TextField
# fields
class SMSMessage(Message)
from_phone = models.CharField
to_phone = models.ForeignKey(FooPhoneNumberModel)
class EmailMessage(Message):
from_email = models.CharField
to_email = models.ForeignKey(FooEmailModel)
class InstantMessage(Message):
from_username = models.CharField
to_username = models.ForeignKey(FooUser)
I'm writing a django testcase for a view that serializes all instances of subclassed messages for a particular user and this part of the test fails when adding more instances
_create_messages()
num_queries = 25
with self.assertNumQueries(num_queries):
response = self.client.get(url)
payload = json.loads(response.content)
self.assertEqual(response.status_code, 200)
self.assertEqual(payload['has_more'], False)
_create_messages()
# fails -- does 45 queries
with self.assertNumQueries(num_queries):
response = self.client.get(url)
I was trying to mess around and see if I could run some type of prefetch? Something like:
messages = Message.objects.prefetch_related(
Prefetch('smsmessage', queryset=SMSMessage.objects.filter(user=user), to_attr='through__smsmessage'),
Prefetch('emailmessage', queryset=EmailMessage.objects.filter(user=user), to_attr='through__emailmessage'),
)
so that the query can execute the same amount of queries whether it's 20 messages or 1000 messages.
Any help is appreciated including explanations of the internals. I've been trying to do things like call select_related('smsmessage')
and select_related('message_ptr__smsmessage')
and the like and my mind is mush right now