diff --git a/django/db/models/base.py b/django/db/models/base.py index fa1e0224d0..d914616b11 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -83,6 +83,11 @@ class Model(object): def _get_pk_val(self): return getattr(self, self._meta.pk.attname) + def _set_pk_val(self, value): + return setattr(self, self._meta.pk.attname, value) + + pk = property(_get_pk_val, _set_pk_val) + def __repr__(self): return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self))) diff --git a/docs/model-api.txt b/docs/model-api.txt index 1f0bb60285..adb9cfceb1 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -1284,6 +1284,17 @@ won't add the automatic ``id`` column. Each model requires exactly one field to have ``primary_key=True``. +The ``pk`` property +------------------- +**New in Django development version** + +Regardless of whether you define a primary key field yourself, or let Django +supply one for you, each model will have a property called ``pk``. It behaves +like a normal attribute on the model, but is actually an alias for whichever +attribute is the primary key field for the model. You can read and set this +value, just as you would for any other attribute, and it will update the +correct field in the model. + Admin options ============= diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py index 0a09579761..58770ef2ce 100644 --- a/tests/modeltests/basic/models.py +++ b/tests/modeltests/basic/models.py @@ -33,6 +33,11 @@ __test__ = {'API_TESTS': """ >>> a.id 1L +# Models have a pk property that is an alias for the primary key attribute (by +# default, the 'id' attribute). +>>> a.pk +1L + # Access database columns via Python attributes. >>> a.headline 'Area man programs in Python' diff --git a/tests/modeltests/custom_pk/models.py b/tests/modeltests/custom_pk/models.py index 375859c897..381d81b987 100644 --- a/tests/modeltests/custom_pk/models.py +++ b/tests/modeltests/custom_pk/models.py @@ -56,6 +56,15 @@ DoesNotExist: Employee matching query does not exist. >>> Employee.objects.filter(pk__in=['ABC123','XYZ456']) [, ] +# The primary key can be accessed via the pk property on the model. +>>> e = Employee.objects.get(pk='ABC123') +>>> e.pk +u'ABC123' + +# Or we can use the real attribute name for the primary key: +>>> e.employee_code +u'ABC123' + # Fran got married and changed her last name. >>> fran = Employee.objects.get(pk='XYZ456') >>> fran.last_name = 'Jones'