Reconciliation / Database Relationship Data in Django

When developing a website for documenting system documentation, I came across a hard nut to crack the "mapping" / relationship between databases in Django.

A simplified model for my local database:

from django.db import models

class Document(models.Model):
    name = models.CharField(max_length=200)
    system_id = models.IntegerField()
    ...

Imaginary model, system data is stored in a remote database.

from django.db import models               

class System(models.Model):     
    name = models.CharField(max_length=200)           
    system_id = models.IntegerField()      
    ...

The idea is that when creating a new document record on my site, the identifier of the associated system should be stored in a local database. When presenting the data, I would have to use the stored identifier to get the system name among other details from the remote database.

, , , . / Document, , , /.

?


, . , . PostgreSQL, , , .

+4
3

django multi-db (-select-a-database)

# This will run on the 'default' database.
Author.objects.all()

# So will this.
Author.objects.using('default').all()

# This will run on the 'other' database.
Author.objects.using('other').all()

The 'default' and 'other' are aliases for you databases.
In your case it would could be 'default' and 'remote'.

, .all() .

Example: System.objects.using('remote').get(id=123456)
+4

get_system(). :

class Document:
    def get_system(self):
       return System.objects.using('remote').get(system_id=self.system_id)

. PostgreSQL . FDW, multidb django - , document β†’ .

, , db .

+1

, Django ORM, db.

: " / Document, "

:

class RemoteObject(object):
    def __init__(self, remote_model, remote_db, field_name):
        # assumes remote db is defined in Django settings and has an
        # associated Django model definition:
        self.remote_model = remote_model
        self.remote_db = remote_db
        # name of id field on model (real db field):
        self.field_name = field_name
        # we will cache the retrieved remote model on the instance
        # the same way that Django does with foreign key fields:
        self.cache_name = '_{}_cache'.format(field_name)

    def __get__(self, instance, cls):
        try:
            rel_obj = getattr(instance, self.cache_name)
        except AttributeError:
            system_id = getattr(instance, self.field_name)
            remote_qs = self.remote_model.objects.using(self.remote_db)
            try:
                rel_obj = remote_qs.get(id=system_id)
            except self.remote_model.DoesNotExist:
                rel_obj = None
            setattr(instance, self.cache_name, rel_obj)
        if rel_obj is None:
            raise self.related.model.DoesNotExist
        else:
            return rel_obj

    def __set__(self, instance, value):
        setattr(instance, self.field_name, value.id)
        setattr(instance, self.cache_name, value)


class Document(models.Model:
    name = models.CharField(max_length=200)
    system_id = models.IntegerField()
    system = RemoteObject(System, 'system_db_name', 'system_id')

, RemoteObject Python, . :
https://docs.python.org/2/howto/descriptor.html

:

>>> doc = Document.objects.get(pk=1)
>>> print doc.system_id
3
>>> print doc.system.id
3
>>> print doc.system.name
'my system'
>>> other_system = System.objects.using('system_db_name').get(pk=5)
>>> doc.system = other_system
>>> print doc.system_id
5

, db:
https://docs.djangoproject.com/en/dev/topics/db/multi-db/#using-routers

using('system_db_name') , System db.

+1

Source: https://habr.com/ru/post/1547567/


All Articles