2. Permissions¶
A permission is what can be done to a model. Django gives every model four -
view_order, add_order, change_order, delete_order - and the library
uses them as they are. The shop declares its own instead, named after what is
done:
class Order(models.Model):
class Status(models.TextChoices):
PENDING = 'pending', _('Pending')
APPROVED = 'approved', _('Approved')
REJECTED = 'rejected', _('Rejected')
DELIVERED = 'delivered', _('Delivered')
customer = models.ForeignKey(
Person, on_delete=models.CASCADE, related_name='orders', verbose_name=_('customer')
)
branch = models.ForeignKey(
Branch, on_delete=models.PROTECT, related_name='orders', verbose_name=_('branch')
)
item = models.CharField(_('item'), max_length=120)
status = models.CharField(
_('status'), max_length=16, choices=Status.choices, default=Status.PENDING
)
#: Set by the shop, never by the customer - empty until it is.
price = models.DecimalField(_('price'), max_digits=10, decimal_places=2, null=True, blank=True)
objects = OrderQuerySet.as_manager()
class Meta:
verbose_name = _('order')
verbose_name_plural = _('orders')
default_permissions = ()
permissions = build_permissions(
'order',
_('orders'),
actions=(*DEFAULT_ACTIONS, 'approve'),
labels={'approve': _('Can approve or reject %(resource)s')},
# Only whoever holds shop.order_view_price reads it.
protected_fields=('price',),
# Only whoever may approve writes these, and only from pending.
status_actions={
'approve': {'field': 'status', 'to': ['approved', 'rejected'], 'from': ['pending']},
},
)
def __str__(self):
return f'{self.item} ({self.branch})'
build_permissions makes:
| permission | from |
|---|---|
shop.order_view, order_create, order_edit, order_delete |
DEFAULT_ACTIONS |
shop.order_approve |
the action added beside them |
shop.order_view_price, order_edit_price |
the protected field - step 6 |
default_permissions = () turns Django's four off, so a model has one set of
names and not two; start-up refuses a model that keeps both (E014). The
status action is step 7.
permission_for(Order, 'edit') answers either style, so nothing else in the
project has to know which a model keeps.
In the admin site¶
Access, Permissions lists every permission, and who holds it:

A permission that exists is given to nobody until somebody gives it: a new one, added in a release, arrives held by nobody.