mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #24693 -- Added label and label_lower property to Model._meta
This commit is contained in:
parent
811d7870a5
commit
69ddc1b3da
@ -37,9 +37,7 @@ class CheckMessage(object):
|
|||||||
elif isinstance(self.obj, models.base.ModelBase):
|
elif isinstance(self.obj, models.base.ModelBase):
|
||||||
# We need to hardcode ModelBase and Field cases because its __str__
|
# We need to hardcode ModelBase and Field cases because its __str__
|
||||||
# method doesn't return "applabel.modellabel" and cannot be changed.
|
# method doesn't return "applabel.modellabel" and cannot be changed.
|
||||||
model = self.obj
|
obj = self.obj._meta.label
|
||||||
app = model._meta.app_label
|
|
||||||
obj = '%s.%s' % (app, model._meta.object_name)
|
|
||||||
else:
|
else:
|
||||||
obj = force_str(self.obj)
|
obj = force_str(self.obj)
|
||||||
id = "(%s) " % self.id if self.id else ""
|
id = "(%s) " % self.id if self.id else ""
|
||||||
|
@ -163,8 +163,8 @@ class DeserializedObject(object):
|
|||||||
self.m2m_data = m2m_data
|
self.m2m_data = m2m_data
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<DeserializedObject: %s.%s(pk=%s)>" % (
|
return "<DeserializedObject: %s(pk=%s)>" % (
|
||||||
self.object._meta.app_label, self.object._meta.object_name, self.object.pk)
|
self.object._meta.label, self.object.pk)
|
||||||
|
|
||||||
def save(self, save_m2m=True, using=None):
|
def save(self, save_m2m=True, using=None):
|
||||||
# Call save on the Model baseclass directly. This bypasses any
|
# Call save on the Model baseclass directly. This bypasses any
|
||||||
|
@ -362,10 +362,9 @@ class ModelState(object):
|
|||||||
try:
|
try:
|
||||||
fields.append((name, field_class(*args, **kwargs)))
|
fields.append((name, field_class(*args, **kwargs)))
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise TypeError("Couldn't reconstruct field %s on %s.%s: %s" % (
|
raise TypeError("Couldn't reconstruct field %s on %s: %s" % (
|
||||||
name,
|
name,
|
||||||
model._meta.app_label,
|
model._meta.label,
|
||||||
model._meta.object_name,
|
|
||||||
e,
|
e,
|
||||||
))
|
))
|
||||||
if not exclude_rels:
|
if not exclude_rels:
|
||||||
@ -423,7 +422,7 @@ class ModelState(object):
|
|||||||
# Make our record
|
# Make our record
|
||||||
bases = tuple(
|
bases = tuple(
|
||||||
(
|
(
|
||||||
"%s.%s" % (base._meta.app_label, base._meta.model_name)
|
base._meta.label_lower
|
||||||
if hasattr(base, "_meta") else
|
if hasattr(base, "_meta") else
|
||||||
base
|
base
|
||||||
)
|
)
|
||||||
|
@ -326,9 +326,7 @@ class ModelBase(type):
|
|||||||
if cls.__doc__ is None:
|
if cls.__doc__ is None:
|
||||||
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.name for f in opts.fields))
|
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.name for f in opts.fields))
|
||||||
|
|
||||||
get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(
|
get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(opts.label_lower)
|
||||||
'%s.%s' % (opts.app_label, opts.model_name)
|
|
||||||
)
|
|
||||||
if get_absolute_url_override:
|
if get_absolute_url_override:
|
||||||
setattr(cls, 'get_absolute_url', get_absolute_url_override)
|
setattr(cls, 'get_absolute_url', get_absolute_url_override)
|
||||||
|
|
||||||
@ -1248,10 +1246,7 @@ class Model(six.with_metaclass(ModelBase)):
|
|||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
"The model has two many-to-many relations through "
|
"The model has two many-to-many relations through "
|
||||||
"the intermediate model '%s.%s'." % (
|
"the intermediate model '%s'." % f.remote_field.through._meta.label,
|
||||||
f.remote_field.through._meta.app_label,
|
|
||||||
f.remote_field.through._meta.object_name
|
|
||||||
),
|
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=cls,
|
obj=cls,
|
||||||
id='models.E003',
|
id='models.E003',
|
||||||
|
@ -76,9 +76,7 @@ class BaseManager(object):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" Return "app_label.model_label.manager_name". """
|
""" Return "app_label.model_label.manager_name". """
|
||||||
model = self.model
|
return '%s.%s' % (self.model._meta.label, self.name)
|
||||||
app = model._meta.app_label
|
|
||||||
return '%s.%s.%s' % (app, model._meta.object_name, self.name)
|
|
||||||
|
|
||||||
def deconstruct(self):
|
def deconstruct(self):
|
||||||
"""
|
"""
|
||||||
|
@ -176,6 +176,14 @@ class Options(object):
|
|||||||
m2m = link.is_relation and link.many_to_many
|
m2m = link.is_relation and link.many_to_many
|
||||||
return link, model, direct, m2m
|
return link, model, direct, m2m
|
||||||
|
|
||||||
|
@property
|
||||||
|
def label(self):
|
||||||
|
return '%s.%s' % (self.app_label, self.object_name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def label_lower(self):
|
||||||
|
return '%s.%s' % (self.app_label, self.model_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def app_config(self):
|
def app_config(self):
|
||||||
# Don't go through get_app_config to avoid triggering imports.
|
# Don't go through get_app_config to avoid triggering imports.
|
||||||
@ -377,7 +385,6 @@ class Options(object):
|
|||||||
case insensitive, so we make sure we are case insensitive here.
|
case insensitive, so we make sure we are case insensitive here.
|
||||||
"""
|
"""
|
||||||
if self.swappable:
|
if self.swappable:
|
||||||
model_label = '%s.%s' % (self.app_label, self.model_name)
|
|
||||||
swapped_for = getattr(settings, self.swappable, None)
|
swapped_for = getattr(settings, self.swappable, None)
|
||||||
if swapped_for:
|
if swapped_for:
|
||||||
try:
|
try:
|
||||||
@ -389,7 +396,7 @@ class Options(object):
|
|||||||
# or as part of validation.
|
# or as part of validation.
|
||||||
return swapped_for
|
return swapped_for
|
||||||
|
|
||||||
if '%s.%s' % (swapped_label, swapped_object.lower()) not in (None, model_label):
|
if '%s.%s' % (swapped_label, swapped_object.lower()) not in (None, self.label_lower):
|
||||||
return swapped_for
|
return swapped_for
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -973,12 +973,12 @@ def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
|
|||||||
(fk.remote_field.model != parent_model and
|
(fk.remote_field.model != parent_model and
|
||||||
fk.remote_field.model not in parent_model._meta.get_parent_list()):
|
fk.remote_field.model not in parent_model._meta.get_parent_list()):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"fk_name '%s' is not a ForeignKey to '%s.%s'."
|
"fk_name '%s' is not a ForeignKey to '%s'." % (fk_name, parent_model._meta.label)
|
||||||
% (fk_name, parent_model._meta.app_label, parent_model._meta.object_name))
|
)
|
||||||
elif len(fks_to_parent) == 0:
|
elif len(fks_to_parent) == 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'%s.%s' has no field named '%s'."
|
"'%s' has no field named '%s'." % (model._meta.label, fk_name)
|
||||||
% (model._meta.app_label, model._meta.object_name, fk_name))
|
)
|
||||||
else:
|
else:
|
||||||
# Try to discover what the ForeignKey from model to parent_model is
|
# Try to discover what the ForeignKey from model to parent_model is
|
||||||
fks_to_parent = [
|
fks_to_parent = [
|
||||||
@ -993,20 +993,16 @@ def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
|
|||||||
if can_fail:
|
if can_fail:
|
||||||
return
|
return
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'%s.%s' has no ForeignKey to '%s.%s'." % (
|
"'%s' has no ForeignKey to '%s'." % (
|
||||||
model._meta.app_label,
|
model._meta.label,
|
||||||
model._meta.object_name,
|
parent_model._meta.label,
|
||||||
parent_model._meta.app_label,
|
|
||||||
parent_model._meta.object_name,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'%s.%s' has more than one ForeignKey to '%s.%s'." % (
|
"'%s' has more than one ForeignKey to '%s'." % (
|
||||||
model._meta.app_label,
|
model._meta.label,
|
||||||
model._meta.object_name,
|
parent_model._meta.label,
|
||||||
parent_model._meta.app_label,
|
|
||||||
parent_model._meta.object_name,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return fk
|
return fk
|
||||||
|
@ -29,6 +29,12 @@ Available ``Meta`` options
|
|||||||
|
|
||||||
app_label = 'myapp'
|
app_label = 'myapp'
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
If you want to represent a model with the format ``app_label.object_name``
|
||||||
|
or ``app_label.model_name`` you can use ``model._meta.label``
|
||||||
|
or ``model._meta.label_lower`` respectively.
|
||||||
|
|
||||||
``db_table``
|
``db_table``
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@ -397,3 +403,26 @@ Django quotes column and table names behind the scenes.
|
|||||||
verbose_name_plural = "stories"
|
verbose_name_plural = "stories"
|
||||||
|
|
||||||
If this isn't given, Django will use :attr:`~Options.verbose_name` + ``"s"``.
|
If this isn't given, Django will use :attr:`~Options.verbose_name` + ``"s"``.
|
||||||
|
|
||||||
|
Read-only ``Meta`` attributes
|
||||||
|
=============================
|
||||||
|
|
||||||
|
``label``
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. attribute:: Options.label
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Representation of the object, returns ``app_label.object_name``, e.g.
|
||||||
|
``'polls.Question'``.
|
||||||
|
|
||||||
|
``label_lower``
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. attribute:: Options.label_lower
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Representation of the model, returns ``app_label.model_name``, e.g.
|
||||||
|
``'polls.question'``.
|
||||||
|
@ -791,4 +791,16 @@ TEST_RESULTS = {
|
|||||||
'content_object_abstract',
|
'content_object_abstract',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
'labels': {
|
||||||
|
AbstractPerson: 'model_meta.AbstractPerson',
|
||||||
|
BasePerson: 'model_meta.BasePerson',
|
||||||
|
Person: 'model_meta.Person',
|
||||||
|
Relating: 'model_meta.Relating',
|
||||||
|
},
|
||||||
|
'lower_labels': {
|
||||||
|
AbstractPerson: 'model_meta.abstractperson',
|
||||||
|
BasePerson: 'model_meta.baseperson',
|
||||||
|
Person: 'model_meta.person',
|
||||||
|
Relating: 'model_meta.relating',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,17 @@ class GetFieldsTests(OptionsBaseTests):
|
|||||||
fields += ["errors"]
|
fields += ["errors"]
|
||||||
|
|
||||||
|
|
||||||
|
class LabelTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_label(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['labels'].items():
|
||||||
|
self.assertEqual(model._meta.label, expected_result)
|
||||||
|
|
||||||
|
def test_label_lower(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['lower_labels'].items():
|
||||||
|
self.assertEqual(model._meta.label_lower, expected_result)
|
||||||
|
|
||||||
|
|
||||||
class DataTests(OptionsBaseTests):
|
class DataTests(OptionsBaseTests):
|
||||||
|
|
||||||
def test_fields(self):
|
def test_fields(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user