Fixed #23879 -- Allowed model migration skip based on feature/vendor

Thanks Carl Meyer for the report and review, and Tim Graham for the
review.
This commit is contained in:
Claude Paroz 2015-04-04 18:07:46 +02:00
parent f043434174
commit 8097e54832
5 changed files with 49 additions and 4 deletions

View File

@ -268,7 +268,7 @@ class Command(BaseCommand):
deferred_sql = []
for app_name, model_list in manifest.items():
for model in model_list:
if model._meta.proxy or not model._meta.managed:
if not model._meta.can_migrate(connection):
continue
if self.verbosity >= 3:
self.stdout.write(

View File

@ -106,7 +106,7 @@ class BaseDatabaseCreation(object):
# Make a function to iteratively return every object
def get_objects():
for model in serializers.sort_dependencies(app_list):
if (not model._meta.proxy and model._meta.managed and
if (model._meta.can_migrate(self.connection) and
router.allow_migrate_model(self.connection.alias, model)):
queryset = model._default_manager.using(self.connection.alias).order_by(model._meta.pk.name)
for obj in queryset.iterator():

View File

@ -106,7 +106,7 @@ class Operation(object):
This is a thin wrapper around router.allow_migrate_model() that
preemptively rejects any proxy, swapped out, or unmanaged model.
"""
if model._meta.proxy or model._meta.swapped or not model._meta.managed:
if not model._meta.can_migrate(connection_alias):
return False
return router.allow_migrate_model(connection_alias, model)

View File

@ -8,6 +8,7 @@ from itertools import chain
from django.apps import apps
from django.conf import settings
from django.core.exceptions import FieldDoesNotExist
from django.db import connections
from django.db.models.fields import AutoField
from django.db.models.fields.proxy import OrderWrt
from django.db.models.fields.related import ManyToManyField
@ -36,7 +37,8 @@ DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
'order_with_respect_to', 'app_label', 'db_tablespace',
'abstract', 'managed', 'proxy', 'swappable', 'auto_created',
'index_together', 'apps', 'default_permissions',
'select_on_save', 'default_related_name')
'select_on_save', 'default_related_name',
'required_db_features', 'required_db_vendor')
class raise_deprecation(object):
@ -111,6 +113,8 @@ class Options(object):
self.get_latest_by = None
self.order_with_respect_to = None
self.db_tablespace = settings.DEFAULT_TABLESPACE
self.required_db_features = []
self.required_db_vendor = None
self.meta = meta
self.pk = None
self.has_auto_field = False
@ -337,6 +341,22 @@ class Options(object):
def __str__(self):
return "%s.%s" % (smart_text(self.app_label), smart_text(self.model_name))
def can_migrate(self, connection):
"""
Return True if the model can/should be migrated on the `connection`.
`connection` can be either a real connection or a connection alias.
"""
if self.proxy or self.swapped or not self.managed:
return False
if isinstance(connection, six.string_types):
connection = connections[connection]
if self.required_db_vendor:
return self.required_db_vendor == connection.vendor
if self.required_db_features:
return all(getattr(connection.features, feat, False)
for feat in self.required_db_features)
return True
@property
def verbose_name_raw(self):
"""

View File

@ -283,6 +283,31 @@ Django quotes column and table names behind the scenes.
If ``proxy = True``, a model which subclasses another model will be treated as
a :ref:`proxy model <proxy-models>`.
``required_db_features``
------------------------
.. attribute:: Options.required_db_features
.. versionadded:: 1.9
List of database features that the current connection should have so that
the model is considered during the migration phase. For example, if you set
this list to ``['gis_enabled']``, the model will only be synchronized on
GIS-enabled databases. It's also useful to skip some models when testing
with several database backends.
``required_db_vendor``
----------------------
.. attribute:: Options.required_db_vendor
.. versionadded:: 1.9
Name of a supported database vendor that this model is specific to. Current
built-in vendor names are: ``sqlite``, ``postgresql``, ``mysql``,
``oracle``. If this attribute is not empty and the current connection vendor
doesn't match it, the model will not be synchronized.
``select_on_save``
------------------