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.