Login

Decoupling models with cross-database relations

Author:
zvikico
Posted:
February 8, 2011
Language:
Python
Version:
1.2
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. Template tag - list punctuation for a list of items by shapiromatron 9 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 5 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

Please login first before commenting.