mirror of
https://github.com/django/django.git
synced 2025-07-05 18:29:11 +00:00
[soc2009/multidb] Added a using option to a Model's Meta class. This allows you to select the default database for a specific model, in addition to the global default
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11135 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
04e3fc8de2
commit
5d462b9ec1
3
TODO.txt
3
TODO.txt
@ -26,7 +26,4 @@ that need to be done. I'm trying to be as granular as possible.
|
||||
|
||||
4) Wait on the merge of the m2m stuff.
|
||||
|
||||
5) Add the ``using`` Meta option. Tests and docs(these are to be assumed at
|
||||
each stage from here on out).
|
||||
|
||||
6) Time permitting add support for a ``DatabaseManager``.
|
||||
|
@ -419,8 +419,7 @@ class Model(object):
|
||||
need for overrides of save() to pass around internal-only parameters
|
||||
('raw', 'cls', and 'origin').
|
||||
"""
|
||||
if using is None:
|
||||
using = DEFAULT_DB_ALIAS
|
||||
using = using or self._meta.using or DEFAULT_DB_ALIAS
|
||||
connection = connections[using]
|
||||
assert not (force_insert and force_update)
|
||||
if cls is None:
|
||||
@ -563,8 +562,7 @@ class Model(object):
|
||||
parent_obj._collect_sub_objects(seen_objs)
|
||||
|
||||
def delete(self, using=None):
|
||||
if using is None:
|
||||
using = DEFAULT_DB_ALIAS
|
||||
using = using or self._meta.using or DEFAULT_DB_ALIAS
|
||||
connection = connections[using]
|
||||
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
|
||||
|
||||
|
@ -21,7 +21,7 @@ get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|
|
||||
DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
|
||||
'unique_together', 'permissions', 'get_latest_by',
|
||||
'order_with_respect_to', 'app_label', 'db_tablespace',
|
||||
'abstract', 'managed', 'proxy')
|
||||
'abstract', 'managed', 'proxy', 'using')
|
||||
|
||||
class Options(object):
|
||||
def __init__(self, meta, app_label=None):
|
||||
@ -47,6 +47,7 @@ class Options(object):
|
||||
self.proxy_for_model = None
|
||||
self.parents = SortedDict()
|
||||
self.duplicate_targets = {}
|
||||
self.using = None
|
||||
|
||||
# To handle various inheritance situations, we need to track where
|
||||
# managers came from (concrete or abstract base classes).
|
||||
@ -487,4 +488,3 @@ class Options(object):
|
||||
Returns the index of the primary key field in the self.fields list.
|
||||
"""
|
||||
return self.fields.index(self.pk)
|
||||
|
||||
|
@ -33,12 +33,14 @@ class QuerySet(object):
|
||||
"""
|
||||
def __init__(self, model=None, query=None):
|
||||
self.model = model
|
||||
connection = connections[DEFAULT_DB_ALIAS]
|
||||
using = model._meta.using or DEFAULT_DB_ALIAS
|
||||
connection = connections[using]
|
||||
self.query = query or sql.Query(self.model, connection)
|
||||
self._result_cache = None
|
||||
self._iter = None
|
||||
self._sticky_filter = False
|
||||
self._using = connections.alias_for_connection(self.query.connection)
|
||||
self._using = (query and
|
||||
connections.alias_for_connection(self.query.connection) or using)
|
||||
|
||||
########################
|
||||
# PYTHON MAGIC METHODS #
|
||||
|
@ -210,6 +210,17 @@ set of fields::
|
||||
|
||||
unique_together = ("driver", "restaurant")
|
||||
|
||||
``using``
|
||||
---------
|
||||
|
||||
.. attribute:: Options.using
|
||||
|
||||
The alias for the default database to be used for this model. If this is not
|
||||
provided the default is ``'default'``. If it is porvided it can be overidden
|
||||
at the ``QuerySet`` level with the ``using()`` method.
|
||||
|
||||
.. versionadded:: TODO
|
||||
|
||||
``verbose_name``
|
||||
----------------
|
||||
|
||||
@ -232,4 +243,3 @@ The plural name for the object::
|
||||
verbose_name_plural = "stories"
|
||||
|
||||
If this isn't given, Django will use :attr:`~Options.verbose_name` + ``"s"``.
|
||||
|
||||
|
@ -25,6 +25,15 @@ thing to note is that your primary database should have the alias
|
||||
``'default'``, and any additional databases you have can have whatever alias
|
||||
you choose.
|
||||
|
||||
Selecting a Database for a ``Model``
|
||||
====================================
|
||||
|
||||
In addition to the global default database for all models, it is possible to
|
||||
select a default database on a per-model level. This is done using the
|
||||
``using`` option in a model's inner ``Meta`` class. When provided this
|
||||
database becomes the default database for all lookups, saves, and deletes for
|
||||
this model. It can be overiden on a per-query basis as described below.
|
||||
|
||||
Selecting a Database for a ``QuerySet``
|
||||
=======================================
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
|
||||
class Book(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
@ -9,3 +10,15 @@ class Book(models.Model):
|
||||
|
||||
class Meta:
|
||||
ordering = ('title',)
|
||||
|
||||
if len(settings.DATABASES) > 1:
|
||||
article_using = filter(lambda o: o != DEFAULT_DB_ALIAS, settings.DATABASES.keys())[0]
|
||||
class Article(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
ordering = ('title',)
|
||||
using = article_using
|
||||
|
@ -6,6 +6,13 @@ from django.test import TestCase
|
||||
|
||||
from models import Book
|
||||
|
||||
try:
|
||||
# we only have these models if the user is using multi-db, it's safe the
|
||||
# run the tests without them though.
|
||||
from models import Article, article_using
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
class ConnectionHandlerTestCase(TestCase):
|
||||
def setUp(self):
|
||||
settings.DATABASES['__test_db'] = {
|
||||
@ -71,3 +78,18 @@ class QueryTestCase(TestCase):
|
||||
|
||||
months = Book.objects.dates('published', 'month').using(db)
|
||||
self.assertEqual(sorted(o.month for o in months), [5, 12])
|
||||
|
||||
if len(settings.DATABASES) > 1:
|
||||
class MetaUsingTestCase(TestCase):
|
||||
def test_meta_using_queries(self):
|
||||
a = Article.objects.create(title="Django Rules!")
|
||||
self.assertEqual(Article.objects.get(title="Django Rules!"), a)
|
||||
for db in connections:
|
||||
if db == article_using:
|
||||
self.assertEqual(Article.objects.using(db).get(title="Django Rules!"), a)
|
||||
else:
|
||||
self.assertRaises(Article.DoesNotExist,
|
||||
lambda: Article.objects.using(db).get(title="Django Rules!"))
|
||||
a.delete()
|
||||
self.assertRaises(Article.DoesNotExist,
|
||||
lambda: Article.objects.get(title="Django Rules!"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user