Advanced topics

Configuring model key

By default, the primary key of a model inheriting from hrefs.BaseReferrableModel (or, by extension, hrefs.starlette.ReferrableModel) is called id. This can be changed by annotating another field with hrefs.PrimaryKey.

from typing import Annotated
from hrefs import BaseReferrableModel, PrimaryKey

class MyModel(BaseReferrableModel):
    my_id: Annotated[int, PrimaryKey]

    # ...the rest of the definitions...

Then MyModel.my_id is the key used by Href[MyModel].

Note

Before Python 3.8, typing_extensions.Annotated can be used to annotate the fields.

Composite keys

It is also possible to annotate multiple fields with PrimaryKey. It will cause the primary key to be a named tuple of the annotated fields:

from typing import Annotated
from hrefs import BaseReferrableModel, PrimaryKey

class Page(BaseReferrableModel):
    book_id: Annotated[int, PrimaryKey]
    page_number: Annotated[int, PrimaryKey]

    # ...the rest of the definition...

When using composite keys with FastAPI or Starlette models, each part of the key must appear in the route template.

from typing import Annotated
from hrefs import PrimaryKey
from hrefs.starlette import ReferrableModel

class Page(ReferrableModel):
    book_id: Annotated[int, PrimaryKey]
    page_number: Annotated[int, PrimaryKey]

    class Config:
        details_view = "get_page"

@app.get("/books/{book_id}/pages/{page_number}", response_model=Page)
def get_page(id: int):
    # implementation

Inheritance

It is possible for a referrable model to inherit another:

class Book(ReferrableModel):
    id: int
    title: str

    class Config:
        details_view = "get_book"

class Textbook(Book):
    subject: str

The derived model Textbook inherits the key id and details view "get_book" from its parent Book.

Primary key annotations are not composable across inheritance, i.e. it is not possible to define a part of the model key in the parent and another part in the derived model. Model key definitions — whether implicit or explicit — should only exist in one class of the inheritance tree.