1
# -*- coding: utf-8 -*-
3
14. Using a custom primary key
5
By default, Django adds an ``"id"`` field to each model. But you can override
6
this behavior by explicitly adding ``primary_key=True`` to a field.
9
from django.conf import settings
10
from django.db import models, transaction, IntegrityError
12
class Employee(models.Model):
13
employee_code = models.IntegerField(primary_key=True, db_column = 'code')
14
first_name = models.CharField(max_length=20)
15
last_name = models.CharField(max_length=20)
17
ordering = ('last_name', 'first_name')
19
def __unicode__(self):
20
return u"%s %s" % (self.first_name, self.last_name)
22
class Business(models.Model):
23
name = models.CharField(max_length=20, primary_key=True)
24
employees = models.ManyToManyField(Employee)
26
verbose_name_plural = 'businesses'
28
def __unicode__(self):
31
__test__ = {'API_TESTS':"""
32
>>> dan = Employee(employee_code=123, first_name='Dan', last_name='Jones')
34
>>> Employee.objects.all()
35
[<Employee: Dan Jones>]
37
>>> fran = Employee(employee_code=456, first_name='Fran', last_name='Bones')
39
>>> Employee.objects.all()
40
[<Employee: Fran Bones>, <Employee: Dan Jones>]
42
>>> Employee.objects.get(pk=123)
44
>>> Employee.objects.get(pk=456)
45
<Employee: Fran Bones>
46
>>> Employee.objects.get(pk=42)
47
Traceback (most recent call last):
49
DoesNotExist: Employee matching query does not exist.
51
# Use the name of the primary key, rather than pk.
52
>>> Employee.objects.get(employee_code__exact=123)
55
# pk can be used as a substitute for the primary key.
56
>>> Employee.objects.filter(pk__in=[123, 456])
57
[<Employee: Fran Bones>, <Employee: Dan Jones>]
59
# The primary key can be accessed via the pk property on the model.
60
>>> e = Employee.objects.get(pk=123)
64
# Or we can use the real attribute name for the primary key:
68
# Fran got married and changed her last name.
69
>>> fran = Employee.objects.get(pk=456)
70
>>> fran.last_name = 'Jones'
72
>>> Employee.objects.filter(last_name__exact='Jones')
73
[<Employee: Dan Jones>, <Employee: Fran Jones>]
74
>>> emps = Employee.objects.in_bulk([123, 456])
78
>>> b = Business(name='Sears')
80
>>> b.employees.add(dan, fran)
82
[<Employee: Dan Jones>, <Employee: Fran Jones>]
83
>>> fran.business_set.all()
85
>>> Business.objects.in_bulk(['Sears'])
86
{u'Sears': <Business: Sears>}
88
>>> Business.objects.filter(name__exact='Sears')
90
>>> Business.objects.filter(pk='Sears')
93
# Queries across tables, involving primary key
94
>>> Employee.objects.filter(business__name__exact='Sears')
95
[<Employee: Dan Jones>, <Employee: Fran Jones>]
96
>>> Employee.objects.filter(business__pk='Sears')
97
[<Employee: Dan Jones>, <Employee: Fran Jones>]
99
>>> Business.objects.filter(employees__employee_code__exact=123)
101
>>> Business.objects.filter(employees__pk=123)
103
>>> Business.objects.filter(employees__first_name__startswith='Fran')
106
# Primary key may be unicode string
107
>>> bus = Business(name=u'jaźń')
110
# The primary key must also obviously be unique, so trying to create a new
111
# object with the same primary key will fail.
113
... sid = transaction.savepoint()
114
... Employee.objects.create(employee_code=123, first_name='Fred', last_name='Jones')
115
... transaction.savepoint_commit(sid)
116
... except Exception, e:
117
... if isinstance(e, IntegrityError):
118
... transaction.savepoint_rollback(sid)
121
... print "Fail with %s" % type(e)
126
# SQLite lets objects be saved with an empty primary key, even though an
127
# integer is expected. So we can't check for an error being raised in that case
128
# for SQLite. Remove it from the suite for this next bit.
129
if settings.DATABASE_ENGINE != 'sqlite3':
130
__test__["API_TESTS"] += """
131
# The primary key must be specified, so an error is raised if you try to create
132
# an object without it.
134
... sid = transaction.savepoint()
135
... Employee.objects.create(first_name='Tom', last_name='Smith')
137
... transaction.savepoint_commit(sid)
139
... except Exception, e:
140
... if isinstance(e, IntegrityError):
141
... transaction.savepoint_rollback(sid)
144
... print "Fail with %s" % type(e)