summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Del Giudice <luis.dg19@gmail.com>2015-04-26 17:05:50 -0400
committerMarkus Holtermann <info@markusholtermann.eu>2015-05-02 16:58:18 +0200
commit69ddc1b3da043195a0f4e09211d395724b42c70b (patch)
tree110548448fb30ecdc9102d0f3a0a1c1dfc946646
parent811d7870a5c7e419a3f041e04a7432d6f28016f8 (diff)
Fixed #24693 -- Added label and label_lower property to Model._meta
-rw-r--r--django/core/checks/messages.py4
-rw-r--r--django/core/serializers/base.py4
-rw-r--r--django/db/migrations/state.py7
-rw-r--r--django/db/models/base.py9
-rw-r--r--django/db/models/manager.py4
-rw-r--r--django/db/models/options.py11
-rw-r--r--django/forms/models.py24
-rw-r--r--docs/ref/models/options.txt29
-rw-r--r--tests/model_meta/results.py12
-rw-r--r--tests/model_meta/tests.py11
10 files changed, 80 insertions, 35 deletions
diff --git a/django/core/checks/messages.py b/django/core/checks/messages.py
index 9245842039..e770f9ccce 100644
--- a/django/core/checks/messages.py
+++ b/django/core/checks/messages.py
@@ -37,9 +37,7 @@ class CheckMessage(object):
elif isinstance(self.obj, models.base.ModelBase):
# We need to hardcode ModelBase and Field cases because its __str__
# method doesn't return "applabel.modellabel" and cannot be changed.
- model = self.obj
- app = model._meta.app_label
- obj = '%s.%s' % (app, model._meta.object_name)
+ obj = self.obj._meta.label
else:
obj = force_str(self.obj)
id = "(%s) " % self.id if self.id else ""
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
index 0f7535a148..e678e78463 100644
--- a/django/core/serializers/base.py
+++ b/django/core/serializers/base.py
@@ -163,8 +163,8 @@ class DeserializedObject(object):
self.m2m_data = m2m_data
def __repr__(self):
- return "<DeserializedObject: %s.%s(pk=%s)>" % (
- self.object._meta.app_label, self.object._meta.object_name, self.object.pk)
+ return "<DeserializedObject: %s(pk=%s)>" % (
+ self.object._meta.label, self.object.pk)
def save(self, save_m2m=True, using=None):
# Call save on the Model baseclass directly. This bypasses any
diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py
index 8165a247a2..b1cba07a9e 100644
--- a/django/db/migrations/state.py
+++ b/django/db/migrations/state.py
@@ -362,10 +362,9 @@ class ModelState(object):
try:
fields.append((name, field_class(*args, **kwargs)))
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,
- model._meta.app_label,
- model._meta.object_name,
+ model._meta.label,
e,
))
if not exclude_rels:
@@ -423,7 +422,7 @@ class ModelState(object):
# Make our record
bases = tuple(
(
- "%s.%s" % (base._meta.app_label, base._meta.model_name)
+ base._meta.label_lower
if hasattr(base, "_meta") else
base
)
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 82b428b0bd..27764bba84 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -326,9 +326,7 @@ class ModelBase(type):
if cls.__doc__ is None:
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.name for f in opts.fields))
- get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(
- '%s.%s' % (opts.app_label, opts.model_name)
- )
+ get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(opts.label_lower)
if 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(
checks.Error(
"The model has two many-to-many relations through "
- "the intermediate model '%s.%s'." % (
- f.remote_field.through._meta.app_label,
- f.remote_field.through._meta.object_name
- ),
+ "the intermediate model '%s'." % f.remote_field.through._meta.label,
hint=None,
obj=cls,
id='models.E003',
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
index e194e28feb..956a8cbd2a 100644
--- a/django/db/models/manager.py
+++ b/django/db/models/manager.py
@@ -76,9 +76,7 @@ class BaseManager(object):
def __str__(self):
""" Return "app_label.model_label.manager_name". """
- model = self.model
- app = model._meta.app_label
- return '%s.%s.%s' % (app, model._meta.object_name, self.name)
+ return '%s.%s' % (self.model._meta.label, self.name)
def deconstruct(self):
"""
diff --git a/django/db/models/options.py b/django/db/models/options.py
index a2cdca82ee..a76b934598 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -177,6 +177,14 @@ class Options(object):
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
def app_config(self):
# Don't go through get_app_config to avoid triggering imports.
return self.apps.app_configs.get(self.app_label)
@@ -377,7 +385,6 @@ class Options(object):
case insensitive, so we make sure we are case insensitive here.
"""
if self.swappable:
- model_label = '%s.%s' % (self.app_label, self.model_name)
swapped_for = getattr(settings, self.swappable, None)
if swapped_for:
try:
@@ -389,7 +396,7 @@ class Options(object):
# or as part of validation.
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 None
diff --git a/django/forms/models.py b/django/forms/models.py
index 59f9d501d5..1ea0dea58b 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -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 not in parent_model._meta.get_parent_list()):
raise ValueError(
- "fk_name '%s' is not a ForeignKey to '%s.%s'."
- % (fk_name, parent_model._meta.app_label, parent_model._meta.object_name))
+ "fk_name '%s' is not a ForeignKey to '%s'." % (fk_name, parent_model._meta.label)
+ )
elif len(fks_to_parent) == 0:
raise ValueError(
- "'%s.%s' has no field named '%s'."
- % (model._meta.app_label, model._meta.object_name, fk_name))
+ "'%s' has no field named '%s'." % (model._meta.label, fk_name)
+ )
else:
# Try to discover what the ForeignKey from model to parent_model is
fks_to_parent = [
@@ -993,20 +993,16 @@ def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
if can_fail:
return
raise ValueError(
- "'%s.%s' has no ForeignKey to '%s.%s'." % (
- model._meta.app_label,
- model._meta.object_name,
- parent_model._meta.app_label,
- parent_model._meta.object_name,
+ "'%s' has no ForeignKey to '%s'." % (
+ model._meta.label,
+ parent_model._meta.label,
)
)
else:
raise ValueError(
- "'%s.%s' has more than one ForeignKey to '%s.%s'." % (
- model._meta.app_label,
- model._meta.object_name,
- parent_model._meta.app_label,
- parent_model._meta.object_name,
+ "'%s' has more than one ForeignKey to '%s'." % (
+ model._meta.label,
+ parent_model._meta.label,
)
)
return fk
diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
index f9a17721cf..1dff215888 100644
--- a/docs/ref/models/options.txt
+++ b/docs/ref/models/options.txt
@@ -29,6 +29,12 @@ Available ``Meta`` options
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``
------------
@@ -397,3 +403,26 @@ Django quotes column and table names behind the scenes.
verbose_name_plural = "stories"
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'``.
diff --git a/tests/model_meta/results.py b/tests/model_meta/results.py
index 858b70b73a..0770b86b2a 100644
--- a/tests/model_meta/results.py
+++ b/tests/model_meta/results.py
@@ -791,4 +791,16 @@ TEST_RESULTS = {
'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',
+ },
}
diff --git a/tests/model_meta/tests.py b/tests/model_meta/tests.py
index 4421c9ef44..390c0fe988 100644
--- a/tests/model_meta/tests.py
+++ b/tests/model_meta/tests.py
@@ -49,6 +49,17 @@ class GetFieldsTests(OptionsBaseTests):
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):
def test_fields(self):