def get_intermediate_model_meta_class(self, klass, from_field_name,
to_field_name,
sort_value_field_name):
managed = True
to_model = self.rel.to
if isinstance(self.rel.to, six.string_types):
if self.rel.to != RECURSIVE_RELATIONSHIP_CONSTANT:
def set_managed(field, model, cls):
field.rel.through._meta.managed = model._meta.managed or cls._meta.managed
add_lazy_relation(klass, self, to_model, set_managed)
else:
managed = klass._meta.managed
else:
managed = klass._meta.managed or to_model._meta.managed
options = {
'db_table': self._get_m2m_db_table(klass._meta),
'managed': managed,
'auto_created': klass,
'app_label': klass._meta.app_label,
'db_tablespace': klass._meta.db_tablespace,
'unique_together': ((from_field_name, to_field_name),),
'ordering': (sort_value_field_name,),
'verbose_name': '%(from)s-%(to)s relationship' % {'from': from_field_name, 'to': to_field_name},
'verbose_name_plural': '%(from)s-%(to)s relationships' % {'from': from_field_name, 'to': to_field_name},
}
# Django 1.6 support.
if hasattr(self.model._meta, 'apps'):
options.update({
'apps': self.model._meta.apps,
})
return type(str('Meta'), (object,), options)
python类RECURSIVE_RELATIONSHIP_CONSTANT的实例源码
def get_rel_to_model_and_object_name(self, klass):
if isinstance(self.rel.to, six.string_types):
if self.rel.to != RECURSIVE_RELATIONSHIP_CONSTANT:
to_model = self.rel.to
to_object_name = to_model.split('.')[-1]
else:
to_model = klass
to_object_name = to_model._meta.object_name
else:
to_model = self.rel.to
to_object_name = to_model._meta.object_name
return to_model, to_object_name
def get_intermediate_model_from_field(self, klass):
name = self.get_intermediate_model_name(klass)
to_model, to_object_name = self.get_rel_to_model_and_object_name(klass)
if self.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass._meta.object_name:
field_name = 'from_%s' % to_object_name.lower()
else:
field_name = get_model_name(klass)
field = models.ForeignKey(klass, related_name='%s+' % name,
**get_foreignkey_field_kwargs(self))
return field_name, field
def get_intermediate_model_to_field(self, klass):
name = self.get_intermediate_model_name(klass)
to_model, to_object_name = self.get_rel_to_model_and_object_name(klass)
if self.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass._meta.object_name:
field_name = 'to_%s' % to_object_name.lower()
else:
field_name = to_object_name.lower()
field = models.ForeignKey(to_model, related_name='%s+' % name,
**get_foreignkey_field_kwargs(self))
return field_name, field
def get_intermediate_model_meta_class(self, klass, from_field_name,
to_field_name,
sort_value_field_name):
managed = True
to_model = self.rel.to
if isinstance(self.rel.to, six.string_types):
if self.rel.to != RECURSIVE_RELATIONSHIP_CONSTANT:
def set_managed(field, model, cls):
field.rel.through._meta.managed = model._meta.managed or cls._meta.managed
add_lazy_relation(klass, self, to_model, set_managed)
else:
managed = klass._meta.managed
else:
managed = klass._meta.managed or to_model._meta.managed
options = {
'db_table': self._get_m2m_db_table(klass._meta),
'managed': managed,
'auto_created': klass,
'app_label': klass._meta.app_label,
'db_tablespace': klass._meta.db_tablespace,
'unique_together': ((from_field_name, to_field_name),),
'ordering': (sort_value_field_name,),
'verbose_name': '%(from)s-%(to)s relationship' % {'from': from_field_name, 'to': to_field_name},
'verbose_name_plural': '%(from)s-%(to)s relationships' % {'from': from_field_name, 'to': to_field_name},
}
# Django 1.6 support.
if hasattr(self.model._meta, 'apps'):
options.update({
'apps': self.model._meta.apps,
})
return type(str('Meta'), (object,), options)
def get_rel_to_model_and_object_name(self, klass):
if isinstance(self.rel.to, six.string_types):
if self.rel.to != RECURSIVE_RELATIONSHIP_CONSTANT:
to_model = self.rel.to
to_object_name = to_model.split('.')[-1]
else:
to_model = klass
to_object_name = to_model._meta.object_name
else:
to_model = self.rel.to
to_object_name = to_model._meta.object_name
return to_model, to_object_name
def get_intermediate_model_from_field(self, klass):
name = self.get_intermediate_model_name(klass)
to_model, to_object_name = self.get_rel_to_model_and_object_name(klass)
if self.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass._meta.object_name:
field_name = 'from_%s' % to_object_name.lower()
else:
field_name = get_model_name(klass)
field = models.ForeignKey(klass, related_name='%s+' % name,
**get_foreignkey_field_kwargs(self))
return field_name, field
def get_intermediate_model_to_field(self, klass):
name = self.get_intermediate_model_name(klass)
to_model, to_object_name = self.get_rel_to_model_and_object_name(klass)
if self.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass._meta.object_name:
field_name = 'to_%s' % to_object_name.lower()
else:
field_name = to_object_name.lower()
field = models.ForeignKey(to_model, related_name='%s+' % name,
**get_foreignkey_field_kwargs(self))
return field_name, field
def _get_model_tuple(self, remote_model, app_label, model_name):
if remote_model == RECURSIVE_RELATIONSHIP_CONSTANT:
return app_label, model_name.lower()
elif '.' in remote_model:
return tuple(remote_model.lower().split('.'))
else:
return app_label, remote_model.lower()
def _get_model_tuple(self, remote_model, app_label, model_name):
if remote_model == RECURSIVE_RELATIONSHIP_CONSTANT:
return app_label, model_name.lower()
elif '.' in remote_model:
return tuple(remote_model.lower().split('.'))
else:
return app_label, remote_model.lower()
def reload_model(self, app_label, model_name):
if 'apps' in self.__dict__: # hasattr would cache the property
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
related_models = set()
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
# Unregister all related models
with self.apps.bulk_update():
for rel_app_label, rel_model_name in related_models:
self.apps.unregister_model(rel_app_label, rel_model_name)
states_to_be_rendered = []
# Gather all models states of those models that will be rerendered.
# This includes:
# 1. All related models of unmigrated apps
for model_state in self.apps.real_models:
if (model_state.app_label, model_state.name_lower) in related_models:
states_to_be_rendered.append(model_state)
# 2. All related models of migrated apps
for rel_app_label, rel_model_name in related_models:
try:
model_state = self.models[rel_app_label, rel_model_name]
except KeyError:
pass
else:
states_to_be_rendered.append(model_state)
# Render all models
self.apps.render_multiple(states_to_be_rendered)
def reload_model(self, app_label, model_name):
if 'apps' in self.__dict__: # hasattr would cache the property
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
related_models = set()
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
# Unregister all related models
with self.apps.bulk_update():
for rel_app_label, rel_model_name in related_models:
self.apps.unregister_model(rel_app_label, rel_model_name)
states_to_be_rendered = []
# Gather all models states of those models that will be rerendered.
# This includes:
# 1. All related models of unmigrated apps
for model_state in self.apps.real_models:
if (model_state.app_label, model_state.name_lower) in related_models:
states_to_be_rendered.append(model_state)
# 2. All related models of migrated apps
for rel_app_label, rel_model_name in related_models:
try:
model_state = self.models[rel_app_label, rel_model_name]
except KeyError:
pass
else:
states_to_be_rendered.append(model_state)
# Render all models
self.apps.render_multiple(states_to_be_rendered)
def _find_reload_model(self, app_label, model_name, delay=False):
if delay:
self.is_delayed = True
related_models = set()
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
pass
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
if delay:
related_models = get_related_models_tuples(old_model)
else:
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
if delay:
related_models.update(get_related_models_tuples(rel_model))
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
return related_models
def reload_model(self, app_label, model_name):
if 'apps' in self.__dict__: # hasattr would cache the property
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
related_models = set()
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
# Unregister all related models
with self.apps.bulk_update():
for rel_app_label, rel_model_name in related_models:
self.apps.unregister_model(rel_app_label, rel_model_name)
states_to_be_rendered = []
# Gather all models states of those models that will be rerendered.
# This includes:
# 1. All related models of unmigrated apps
for model_state in self.apps.real_models:
if (model_state.app_label, model_state.name_lower) in related_models:
states_to_be_rendered.append(model_state)
# 2. All related models of migrated apps
for rel_app_label, rel_model_name in related_models:
try:
model_state = self.models[rel_app_label, rel_model_name]
except KeyError:
pass
else:
states_to_be_rendered.append(model_state)
# Render all models
self.apps.render_multiple(states_to_be_rendered)
def reload_model(self, app_label, model_name):
if 'apps' in self.__dict__: # hasattr would cache the property
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
related_models = set()
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
# Unregister all related models
with self.apps.bulk_update():
for rel_app_label, rel_model_name in related_models:
self.apps.unregister_model(rel_app_label, rel_model_name)
states_to_be_rendered = []
# Gather all models states of those models that will be rerendered.
# This includes:
# 1. All related models of unmigrated apps
for model_state in self.apps.real_models:
if (model_state.app_label, model_state.name_lower) in related_models:
states_to_be_rendered.append(model_state)
# 2. All related models of migrated apps
for rel_app_label, rel_model_name in related_models:
try:
model_state = self.models[rel_app_label, rel_model_name]
except KeyError:
pass
else:
states_to_be_rendered.append(model_state)
# Render all models
self.apps.render_multiple(states_to_be_rendered)
def _find_reload_model(self, app_label, model_name, delay=False):
if delay:
self.is_delayed = True
related_models = set()
try:
old_model = self.apps.get_model(app_label, model_name)
except LookupError:
pass
else:
# Get all relations to and from the old model before reloading,
# as _meta.apps may change
if delay:
related_models = get_related_models_tuples(old_model)
else:
related_models = get_related_models_recursive(old_model)
# Get all outgoing references from the model to be rendered
model_state = self.models[(app_label, model_name)]
# Directly related models are the models pointed to by ForeignKeys,
# OneToOneFields, and ManyToManyFields.
direct_related_models = set()
for name, field in model_state.fields:
if field.is_relation:
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
continue
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
direct_related_models.add((rel_app_label, rel_model_name.lower()))
# For all direct related models recursively get all related models.
related_models.update(direct_related_models)
for rel_app_label, rel_model_name in direct_related_models:
try:
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
except LookupError:
pass
else:
if delay:
related_models.update(get_related_models_tuples(rel_model))
else:
related_models.update(get_related_models_recursive(rel_model))
# Include the model itself
related_models.add((app_label, model_name))
return related_models
def __init__(self, to_model, base_field=None, size=None, related_name=None, symmetrical=None,
related_query_name=None, limit_choices_to=None, to_field=None, db_constraint=False, **kwargs):
try:
to = to_model._meta.model_name
except AttributeError:
assert isinstance(to_model, six.string_types), (
"%s(%r) is invalid. First parameter to ForeignKey must be "
"either a model, a model name, or the string %r" % (
self.__class__.__name__, to_model,
RECURSIVE_RELATIONSHIP_CONSTANT,
)
)
to = str(to_model)
else:
# For backwards compatibility purposes, we need to *try* and set
# the to_field during FK construction. It won't be guaranteed to
# be correct until contribute_to_class is called. Refs #12190.
to_field = to_field or (to_model._meta.pk and to_model._meta.pk.name)
if not base_field:
field = to_model._meta.get_field(to_field)
if not field.is_relation:
base_field_type = type(field)
internal_type = field.get_internal_type()
if internal_type == 'AutoField':
pass
elif internal_type == 'BigAutoField':
base_field = models.BigIntegerField()
elif hasattr(field, 'max_length'):
base_field = base_field_type(max_length = field.max_length)
else:
base_field = base_field_type()
if not base_field:
base_field = models.IntegerField()
if symmetrical is None:
symmetrical = (to == RECURSIVE_RELATIONSHIP_CONSTANT)
kwargs['rel'] = self.rel_class(
self, to, to_field,
related_name=related_name,
related_query_name=related_query_name,
limit_choices_to=limit_choices_to,
symmetrical=symmetrical,
)
self.has_null_arg = 'null' in kwargs
self.db_constraint = db_constraint
self.to = to
if 'default' not in kwargs.keys():
kwargs['default'] = []
kwargs['blank'] = True
self.from_fields = ['self']
self.to_fields = [to_field]
super(ArrayManyToManyField, self).__init__(base_field, size=size, **kwargs)