Skip to main content

GenericForeignKey that can reference objects across projects

Project description

django-federated-foreign-key

A GenericForeignKey drop-in with ability to point to items in another server

Install from source using pip:

pip install -e .

GenericForeignKey

A generic foreign key allows pointing to objects of any type. To do this, it uses 2 existing fields on the model:

  • A reference to a ContentType entry and
  • An id of the related object

https://docs.djangoproject.com/en/5.2/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericForeignKey

Difference for Federated Foreign Key

The limitation that we are addressing here is that ContentType is only designed to reference models that exist within the local system. It is also taken as obvious that the object_id (the related object id) is the id of the object, in the related table, in the same database.

The intent of a federated foreign key is to provide the same interface, but expand this to allow referencing objects in different databases.

Usage

Add federated_foreign_key to INSTALLED_APPS and define FEDERATION_PROJECT_NAME in your Django settings:

FEDERATION_PROJECT_NAME = 'project_a'
INSTALLED_APPS = [
    'django.contrib.contenttypes',
    'federated_foreign_key',
    # your apps...
]

Use FederatedForeignKey in place of GenericForeignKey together with GenericContentType.

Example

from federated_foreign_key.fields import FederatedForeignKey
from federated_foreign_key.models import GenericContentType

class Reference(models.Model):
    content_type = models.ForeignKey(GenericContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = FederatedForeignKey("content_type", "object_id")

Development

Install development requirements and run linting and tests:

pip install -r requirements-dev.txt
pip install -e .
pip install -e example_project
ruff check .
flake8
pytest -q
# Run Django's contenttypes tests as shipped in `dj_tests/`
# Use --parallel=1 to avoid multiprocessing issues
python dj_tests/runtests.py contenttypes_tests --parallel=1

Demo

Run the included run_demo.sh script to start two demo servers. The main example_project exposes /books/ which lists local books and books fetched from the remote_project server. SQLite database files are created in each project directory when the script sets the DATABASE_NAME environment variable.

./run_demo.sh

Provided that is running, go visit in your browser the URL:

http://localhost:8000/books/

You should see the example_project showing the reqest, but in the logs from the remote_project, it should show requests coming from the example_project. It shows the names being filled in with values from the remote server.

Remote Model Use Cases

There are 3 cases that this is likely to be used for. This library doesn't provide you with everything you need, just the relationship to store a content_object that may be non-local.

  1. Same model, different servers, different data
  2. Shared model, different servers, different data
  3. Different model, on remote server

Same model, different servers

This is what is illustrated in the demo. Consider that you have 2 book shops, and they both have their own listings of books. A book listing will be duplicate, in the sense that both entries reference the same book. But maybe the two shops have different prices. This helps present a unified list of shopping options for books. Each entry could have its own shopping cart icon, to buy that book from that server, at that cost.

Synchronized tables

Illustration

This shows how FederatedForeignKey works compared to GenericForeignKey.

The object_id values specify the row location in all cases.

graph TD
  %% First scenario: GenericForeignKey
  subgraph GenericForeignKey
    GFKPointerTable[Generic FK Table]
    ContentType[ContentType Table]
    TargetTable[Target Model Table]

    GFKPointerTable -->|content_type_id| ContentType
    GFKPointerTable -->|object_id| TargetTable
  end

  %% Second scenario: FederatedForeignKey
  subgraph FederatedForeignKey
    FFKPointerTable[Federated FK Table]
    GenericContentType[GenericContentType Table]
    LocalTargetTable[Local Target Table]

    FFKPointerTable -->|generic_content_type_id| GenericContentType
    FFKPointerTable -->|object_id| LocalTargetTable
  end

  subgraph External Database
    RemoteTargetTable[Remote Target Table]
  end

  FFKPointerTable -->|object_id| RemoteTargetTable

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_federated_foreign_key-0.1.0.tar.gz (14.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_federated_foreign_key-0.1.0-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file django_federated_foreign_key-0.1.0.tar.gz.

File metadata

File hashes

Hashes for django_federated_foreign_key-0.1.0.tar.gz
Algorithm Hash digest
SHA256 569d5ec5ab7c26dd2511fe13d59102725df77887916c385221a7bb5350c15aa4
MD5 46e51993a995f53a6fc61bac48ec932d
BLAKE2b-256 4dc64a948fefcbc2c72d09b5cc75a7e7f0f6b13f4fb35d459644696bf745ceae

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_federated_foreign_key-0.1.0.tar.gz:

Publisher: release.yml on AlanCoding/django-federated-foreign-key

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_federated_foreign_key-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_federated_foreign_key-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 436914659382fbc03e65b7805398bab73dca8ce2b4c21f1e77693051d9eb7341
MD5 00eece14adb6dc0d715f462d3ad95ea3
BLAKE2b-256 8d90ff7831e05cbb61012d89e4caa1b1cc08980f5994b95b1b04e81b888ff784

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_federated_foreign_key-0.1.0-py3-none-any.whl:

Publisher: release.yml on AlanCoding/django-federated-foreign-key

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page