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:
parent
f043434174
commit
8097e54832
|
@ -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(
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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``
|
||||
------------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue