First Look at Django 2.1: Model View Permissions
Django 2.1 landed with a feature teams have wanted for years: model view permissions. Finally, you can give users read-only access to the admin without ugly workarounds.
The Problem Before
Django’s permission system had add, change, and delete. But no view permission. If you wanted someone to see data without modifying it, you had to:
- Give them change permission and make fields read-only
- Create custom admin views
- Build a separate read-only interface
All hacky solutions for a common need.
View Permissions in 2.1
Now every model automatically gets a view permission:
# Automatically created permissions for Book model:
# - books.add_book
# - books.change_book
# - books.delete_book
# - books.view_book # NEW!
Admin Integration
The admin respects view permissions automatically:
from django.contrib import admin
from .models import Book
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
pass
A user with only view_book permission can:
- See the model in the admin
- View the list of objects
- View individual object details
- Not add, change, or delete anything
Checking Permissions in Code
# In views
if request.user.has_perm('books.view_book'):
# Show read-only view
# In templates
{% if perms.books.view_book %}
<a href="{% url 'book-list' %}">View Books</a>
{% endif %}
Custom Permissions
You can still define custom permissions:
class Book(models.Model):
title = models.CharField(max_length=200)
class Meta:
permissions = [
("export_book", "Can export books to CSV"),
("archive_book", "Can archive books"),
]
Migration Considerations
When upgrading to 2.1, view permissions are created automatically. Run migrations:
python manage.py migrate
Existing users won’t have view permission granted automatically—you’ll need to assign it.
Granting Permissions
Via Admin
Add users to groups with appropriate permissions.
Programmatically
from django.contrib.auth.models import Permission
view_perm = Permission.objects.get(codename='view_book')
user.user_permissions.add(view_perm)
Default for Staff
You might want all staff to have view access:
from django.contrib.auth.signals import user_logged_in
def grant_view_permissions(sender, user, request, **kwargs):
if user.is_staff:
# Grant view permissions for all models
view_perms = Permission.objects.filter(codename__startswith='view_')
user.user_permissions.add(*view_perms)
Other 2.1 Features
While we’re here, a few more highlights:
Model __str__ in Admin
The admin now shows __str__() in more places by default.
Relative Database URLs
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3', # Path object support
}
}
Minor Improvements
distanceandlengthforSearchVector- Better error messages
- Performance improvements
Upgrade Path
From Django 2.0:
- Update requirements:
Django>=2.1,<2.2 - Run
python manage.py checkfor deprecation warnings - Run migrations
- Test permission-sensitive flows
The upgrade should be smooth—no major breaking changes.
Final Thoughts
View permissions solve a real problem elegantly. If you’ve been waiting for this feature, Django 2.1 delivers.
For most projects, the upgrade is worth it just for this addition. Cleaner permission models make applications easier to reason about and maintain.
Small features, big improvements.