So I did some basic poking around with managers, etc.

I noticed what 'may be' a 3 part solution to keep a model on one and
only one db:

First, we should modify the initial queryset to use our preferred db.
We can do this by adding a custom manager, with an overridden
get_query_set():

class PartionedManager(models.Manager):
    use_for_related_fields = True #Forces this manager to be used
during related lookups
    def __init__(self, *args, **kwargs):
        self.forced_using = kwargs.pop('using', 'default')
        super(PartionedManager, self).__init__(*args, **kwargs)
    def get_query_set(self):
        return super(PartionedManager, self).get_query_set().using
(self.forced_using)

However, this doesn't solve the ability to .save() into another db, so
lets create an abstract model our real stuff can inherit from:

class PartitionedModel(models.Model):
    objects = PartitionedManager(using='aux')
    def save(self, *args, **kwargs):
        kwargs['using'] = 'adsales' #Makes sure instances are saved in
the proper place
        super(AdSalesModel, self).save(*args, **kwargs)
    class Meta:
        abstract = True

class ConcreteModel(PartitionedModel):
    name = models.CharField(max_length=255)

class SomeModelOnTheMainDB(models.Model):
    name = models.CharField(max_length=255)
    concrete = models.ForeignKey(ConcreteModel)

So far so good. However, relations still throw an error that models
can't be found. The reason for this is:

http://code.djangoproject.com/browser/django/trunk/django/db/models/fields/related.py#L262

The related code instantiates the manager, and then immediately
changes it's db with a .using() clause to wherever the original model
came from (e.g., another db). Since we want to force this, we have two
options:

1) get a django patch that can find another class attribute on the
manager and optionally not apply that using(), or apply a forced using
(), or
2) hack it!:

class PartionedManager(models.Manager):
    use_for_related_fields = True #Forces this manager to be used
during related lookups
    def __init__(self, *args, **kwargs):
        self.forced_using = kwargs.pop('using', 'default')
        super(PartionedManager, self).__init__(*args, **kwargs)
    def get_query_set(self):
        qs = super(PartionedManager, self).get_query_set().using
(self.forced_using)
        qs._real_using = qs.using
        qs.using = lambda new_using: qs._real_using(qs._db) #Disable
changing db with .using() - required because related manager tries to
set .using after we return the qs
        return qs

class PartitionedModel(models.Model):
    objects = PartitionedManager(using='aux')
    def save(self, *args, **kwargs):
        kwargs['using'] = 'adsales' #Makes sure instances are saved in
the proper place
        super(AdSalesModel, self).save(*args, **kwargs)
    class Meta:
        abstract = True

class ConcreteModel(PartitionedModel):
    name = models.CharField(max_length=255)

ConcreteModel here is now tied to a db. I'm testing this code in
production, and was wondering what everyone thought?

--

You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.


Reply via email to