I have a data structure in which a Document
has many Blocks
which have exactly one Paragraph
or Header
. A simplified implementation:
class Document(models.Model):
title = models.CharField()
class Block(models.Model):
document = models.ForeignKey(to=Document)
content_block_type = models.ForeignKey(to=ContentType)
content_block_id = models.CharField()
content_block = GenericForeignKey(
ct_field="content_block_type",
fk_field="content_block_id",
)
class Paragraph(models.Model):
text = models.TextField()
class Header(models.Model):
text = models.TextField()
level = models.SmallPositiveIntegerField()
(Note that there is an actual need for having Paragraph
and Header
in separate models unlike in the implementation above.)
I use jinja2
to template a Latex file for the document. Templating is slow though as jinja performs a new database query for every Block and Paragraph or Header.
template = get_template(template_name="latex_templates/document.tex", using="tex")
return template.render(context={'script': self.script})
\documentclass[a4paper,10pt]{report}
\begin{document}
{% for block in chapter.block_set.all() %}
{% if block.content_block_type.name == 'header' %}
\section{ {{- block.content_block.latex_text -}} }
{% elif block.content_block_type.name == 'paragraph' %}
{{ block.content_block.latex_text }}
{% endif %}
{% endfor %}
\end{document}
(content_block.latex_text()
is a function that converts a HTML string to a Latex string)
Hence I would like to prefetch script.blocks
and blocks.content_block
. I understand that there are two methods for prefetching in Django:
select_related()
performs aJOIN
query but only works onForeignKeys
. It would work forscript.blocks
but not forblocks.content_block
.prefetch_related()
works with GenericForeignKeys as well, but if I understand the docs correctly, it can only fetch oneContentType
at a time while I have two.
Is there any way to perform the necessary prefetching here? Thank you for your help.