Postponed annotations
Self-referencing Models
When you want to reference the same model during declaration to create a
relation you need to declare the referenced model as a ForwardRef
, as during the declaration
the class is not yet ready and python by default won't let you reference it.
Although you might be tempted to use future annotations or simply quote the name with ""
it won't work
as ormar
is designed to work with explicitly declared ForwardRef
.
First, you need to import the required ref from typing.
1 |
|
Now we need a sample model and a reference to the same model, which will be used to create a self referencing relation.
1 2 3 4 5 6 7 8 9 10 11 |
|
That's so simple. But before you can use the model you need to manually update the references so that they lead to the actual models.
Warning
If you try to use the model without updated references, ModelError
exception will be raised.
So in our example above any call like following will cause exception
1 2 3 4 5 6 |
|
To update the references call the update_forward_refs
method on each model
with forward references, only after all related models were declared.
So in order to make our previous example work we need just one extra line.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Of course the same can be done with ManyToMany relations in exactly same way, both for to and through parameters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Cross model relations
The same mechanism and logic as for self-reference model can be used to link multiple different models between each other.
Of course ormar
links both sides of relation for you,
creating a reverse relation with specified (or default) related_name
.
But if you need two (or more) relations between any two models, that for whatever reason
should be stored on both sides (so one relation is declared on one model,
and other on the second model), you need to use ForwardRef
to achieve that.
Look at the following simple example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Warning
Remember that related_name
needs to be unique across related models regardless
of how many relations are defined.