Login

Decoupling models with cross-database relations

Author:
zvikico
Posted:
February 8, 2011
Language:
Python
Version:
1.2
Tags:
django model database
Score:
-1 (after 1 ratings)

The snippet enables decoupling model classes, associated with a ForeignKey, for the purpose of separating them into two databases. Looking at the following example:

class Reporter(models.Model):
    ...

class Article(models.Model):
    reporter = models.ForeignKey(Reporter)

We want to separate the Reporter and Article into two separate databases, but this won't work in Django because of the cross model relations. The solution is to use an ID field and not a ForeignKey one. This makes the access very uncomfortable. The above class will make this a bit less awkward. It doesn't support the RelatedManager, but it will support accessing the related field as you normally would.

The article class will look like this (assuming the reporter model id field is an IntegerField):

class Article(DecoupledModel):
    reporter_id = models.IntegerField()

    _linked_fields = {
        'reporter': Reporter,
    }

Once you have an article object, you can access the reporter as you normally would for both read and writing. For example:

my_reporter = article1.reporter
article2.reporter = my_reporter
 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
30
31
32
33
34
35
36
37
38
39
class DecoupledModel(models.Model):

    class Meta:
        abstract = True

    _linked_fields = {
        # 'field': MyModel,
    }

    def __getattr__(self, name):
        fields = self.__class__._linked_fields
        if name in fields:
            model_class = fields[name]
            model = None
            try:
                pk = getattr(self, name + '_id')
                if pk:
                    model = model_class.objects.get(pk = pk)
            except:
                pass
            self.__dict__[name] = model
            return model
        else:
            return super(DecoupledModel, self).__getattribute__(name)

    def __setattr__(self, name, value):
        fields = self.__class__._linked_fields
        if name in fields:
            pk = 0
            try:
                if value:
                    pk = value.pk
            except:
                pass
            self.__dict__[name + '_id'] = pk
            self.__dict__[name] = value
            return pk
        else:
            return super(DecoupledModel, self).__setattr__(name, value)

More like this

  1. Manager for something like __inall by apollo13 7 years, 4 months ago
  2. Dynamically add css-classes to formfields by Lacour 3 years, 8 months ago
  3. Allow filtering and ordering by counts of related query results by exogen 7 years, 11 months ago
  4. i18n base model for translatable content by foxbunny 6 years, 8 months ago
  5. Export Related as JSON Admin Action by johnboxall 5 years, 9 months ago

Comments

Please login first before commenting.