2017-02-03 13:42:15 +08:00
|
|
|
from collections import namedtuple
|
|
|
|
|
|
|
|
from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT
|
|
|
|
|
|
|
|
|
2017-07-01 02:51:08 +08:00
|
|
|
def is_referenced_by_foreign_key(state, model_name_lower, field, field_name):
|
|
|
|
for state_app_label, state_model in state.models:
|
|
|
|
for _, f in state.models[state_app_label, state_model].fields:
|
|
|
|
if (f.related_model and
|
|
|
|
'%s.%s' % (state_app_label, model_name_lower) == f.related_model.lower() and
|
|
|
|
hasattr(f, 'to_fields')):
|
|
|
|
if (f.to_fields[0] is None and field.primary_key) or field_name in f.to_fields:
|
|
|
|
return True
|
|
|
|
return False
|
2017-02-03 13:42:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
class ModelTuple(namedtuple('ModelTupleBase', ('app_label', 'model_name'))):
|
|
|
|
@classmethod
|
|
|
|
def from_model(cls, model, app_label=None, model_name=None):
|
|
|
|
"""
|
|
|
|
Take a model class or a 'app_label.ModelName' string and return a
|
|
|
|
ModelTuple('app_label', 'modelname'). The optional app_label and
|
|
|
|
model_name arguments are the defaults if "self" or "ModelName" are
|
|
|
|
passed.
|
|
|
|
"""
|
|
|
|
if isinstance(model, str):
|
|
|
|
if model == RECURSIVE_RELATIONSHIP_CONSTANT:
|
|
|
|
return cls(app_label, model_name)
|
|
|
|
if '.' in model:
|
|
|
|
return cls(*model.lower().split('.', 1))
|
|
|
|
return cls(app_label, model.lower())
|
|
|
|
return cls(model._meta.app_label, model._meta.model_name)
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
if isinstance(other, ModelTuple):
|
|
|
|
# Consider ModelTuple equal if their model_name is equal and either
|
|
|
|
# one of them is missing an app_label.
|
|
|
|
return self.model_name == other.model_name and (
|
|
|
|
self.app_label is None or other.app_label is None or self.app_label == other.app_label
|
|
|
|
)
|
|
|
|
return super().__eq__(other)
|
|
|
|
|
|
|
|
|
|
|
|
def field_references_model(field, model_tuple):
|
|
|
|
"""Return whether or not field references model_tuple."""
|
|
|
|
remote_field = field.remote_field
|
|
|
|
if remote_field:
|
|
|
|
if ModelTuple.from_model(remote_field.model) == model_tuple:
|
|
|
|
return True
|
|
|
|
through = getattr(remote_field, 'through', None)
|
|
|
|
if through and ModelTuple.from_model(through) == model_tuple:
|
|
|
|
return True
|
|
|
|
return False
|