How to add a relationship to a GeneratedField in Django
Context
I have a model:
class Article(models.Model):
id = models.UUIDField(default=uuid4, editable=False, unique=True, primary_key=True)
paper_id: UUID | None
paper = models.ForeignKey["Paper"](
"Paper",
on_delete=models.CASCADE,
related_name="articles",
null=True,
blank=True,
)
website_id: UUID | None
website = models.ForeignKey["Website"](
"Website",
on_delete=models.CASCADE,
related_name="articles",
null=True,
blank=True,
)
I then have a view that unifies Paper
and Website
:
class Source(pg.View):
sql = """
SELECT ...
FROM papers
UNION ALL
SELECT ...
FROM websites
;
"""
id = models.UUIDField(unique=True, primary_key=True)
# ...
Question
I'd like to make it so from a Source
model I can get the articles
(e.g. source.articles.all()
).
How can I do that?
What have I tried?
I've tried to add this field to Article
:
source_id = models.GeneratedField(
expression=Coalesce(F("paper_id"), F("website_id")),
output_field=models.UUIDField(),
db_persist=False,
)
source = models.ForeignKey["Source"](
"Source",
on_delete=models.DO_NOTHING,
related_name="articles",
db_column="source_id",
to_field="id",
null=True,
editable=False,
)
But when creating the migration I get:
(models.E006) The field 'source' clashes with the field 'source_id' from model 'Article'.
I believe the problem is that you're running into a Django limitation:
ForeignKey fields auto-create a <field>_id
attribute at the database level, so you cannot have both a model field named source_id
and a ForeignKey source
field, which causes the clash.
As @willeM_VanOnsem suggested, use an @property
as a limited workaround.