Django Staff v 1.2¶
Goals¶
In the Django Authentication package all users use the same model/profile. This can be a drawback if you have lots of users and you want different information stored for your staff members, such as bio, contact info, etc. It is also handy for linking to models for author fields so the lookup is quicker.
The staff models are automatically created and managed by the is_staff
property of Users
. The staff profile is automatically added to the User
admin screen.
Contents¶
Getting Started¶
Installation¶
pip install django-staff
- Add to
INSTALLED_APPS
insettings.py
How it works¶
Django Staff modifies (monkey patches) Django’s built-in
User
model’s admin, adding an inline form to theStaff
model.Django Staff registers a listener to updates to the
User
model.Three possible actions can happen when a
User
is created or changed:- A staff object is created, linked to the user object and permission is added for all available sites.
- The existing staff object is updated, keeping the first name, last name and e-mail in sync and also confirming the active status of the staff object.
- The existing staff object is marked as inactive
Using Django Staff¶
- Create a new
User
- Make sure their
staff status
is checked - Click the
Save and continue editing
button. - When the page reloads, you’ll notice the additional fields at the bottom of the page.
Customizing StaffMember¶
While the StaffMember
model is meant to be general, sometimes you need something extra. You can create your own subclass of StaffMember
for tweaking. In the example project you can browse the mystaff
app. To test it out:
- Comment out
'staff',
fromINSTALLED_APPS
insettings.py
- Uncomment
'mystaff',
fromINSTALLED_APPS
insettings.py
- Delete the
dev.db
file - Run
./manage.py syncdb
- Create a new superuser when prompted
Create the custom class¶
Your custom StaffMember
model is going to subclass BaseStaffMember
, which is an abstract version of StaffMember
. Add your additional fields to the class.
1 2 3 4 5 6 7 8 9 10 11 12 | from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from staff.models import BaseStaffMember, get_staff_updater
class MyStaffMember(BaseStaffMember):
github = models.CharField(max_length=50, blank=True)
update_staff_member = get_staff_updater(MyStaffMember)
post_save.connect(update_staff_member, sender=User)
|
Connect the signal¶
You need to manually connect the post_save
signal to a function that keeps your custom staff member class in sync.
1 2 3 4 5 6 7 8 9 10 11 12 | from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from staff.models import BaseStaffMember, get_staff_updater
class MyStaffMember(BaseStaffMember):
github = models.CharField(max_length=50, blank=True)
update_staff_member = get_staff_updater(MyStaffMember)
post_save.connect(update_staff_member, sender=User)
|
- Import
get_staff_updater()
fromstaff.models
. See line 5 in the example. - Execute it, passing in your model, and assign it to a variable. See line 11 in the example.
- Import
post_save
fromdjango.db.models.signals
. See line 2 in the example. - Finally connect the
post_save
signal to your staff updater variable as in line 12 in the example.
Create your admin class¶
The admin class is more complicated. It consists of three parts: customizing the StaffMemberAdmin
class, creating a custom UserAdmin
, and finally swapping out the currently registered UserAdmin
class with yours.
Your own admin class¶
Your admin class simply needs to redefine the fieldsets and model of the StaffMemberAdmin
class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from staff.admin import StaffMemberAdmin
from .models import MyStaffMember
class MyStaffMemberAdmin(StaffMemberAdmin):
fieldsets = (
('Personal Info', {'fields': ('bio', 'photo', 'website', 'phone',)}),
('Social Media', {'fields': ('github', 'twitter', 'facebook', 'google_plus')}),
('Responsibilities', {'fields': ('sites',)}),
)
model = MyStaffMember
class MyStaffUserAdmin(UserAdmin):
"""
Subclasses the UserAdmin to add the staffmember as an inline.
"""
inlines = [MyStaffMemberAdmin, ]
admin.site.unregister(User)
admin.site.register(User, MyStaffUserAdmin)
|
The class is very straightforward. Since we only added one field, github
, we copy the fieldsets
value from the base class and add that field in.
Then we set the model to our new model.
Making a custom User admin class¶
We need to add an inline class to the current UserAdmin
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from staff.admin import StaffMemberAdmin
from .models import MyStaffMember
class MyStaffMemberAdmin(StaffMemberAdmin):
fieldsets = (
('Personal Info', {'fields': ('bio', 'photo', 'website', 'phone',)}),
('Social Media', {'fields': ('github', 'twitter', 'facebook', 'google_plus')}),
('Responsibilities', {'fields': ('sites',)}),
)
model = MyStaffMember
class MyStaffUserAdmin(UserAdmin):
"""
Subclasses the UserAdmin to add the staffmember as an inline.
"""
inlines = [MyStaffMemberAdmin, ]
admin.site.unregister(User)
admin.site.register(User, MyStaffUserAdmin)
|
This is merely sublassing the existing UserAdmin
and adding our own inlines
attribute equal to a list containing the new admin class defined above.
Re-registering the UserAdmin¶
Now we carefully swap the old UserAdmin
with our UserAdmin
subclass.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from staff.admin import StaffMemberAdmin
from .models import MyStaffMember
class MyStaffMemberAdmin(StaffMemberAdmin):
fieldsets = (
('Personal Info', {'fields': ('bio', 'photo', 'website', 'phone',)}),
('Social Media', {'fields': ('github', 'twitter', 'facebook', 'google_plus')}),
('Responsibilities', {'fields': ('sites',)}),
)
model = MyStaffMember
class MyStaffUserAdmin(UserAdmin):
"""
Subclasses the UserAdmin to add the staffmember as an inline.
"""
inlines = [MyStaffMemberAdmin, ]
admin.site.unregister(User)
admin.site.register(User, MyStaffUserAdmin)
|
Django’s admin has the ability to both register an admin class and unregister an admin class. After removing any admin classes associated with the User
class, we register and associate our custom user admin class.
Gather the templates¶
Django staff includes a set of templates for various Django versions. Since we’ll remove 'staff'
from INSTALLED_APPS
, Django won’t find them any more. We need to copy them into either the project’s templates directory or your application’s template directory.
The templates, named staff.html
and staff13.html
, need to go into:
templates
admin
edit_inline
staff.html
staff13.html
Remove staff from INSTALLED_APPS¶
If Django Staff is still included in your INSTALLED_APPS
setting, you’ll have a bit of redundancy. Make sure that 'staff'
is not in that list. It still must remain available to your new application, so don’t don’t uninstall the library.
Reference¶
Settings¶
Default Settings¶
DEFAULT_SETTINGS = {
'PHOTO_STORAGE': settings.DEFAULT_FILE_STORAGE,
'ORDERING': ('last_name', 'first_name'),
}
Staff Model Reference¶
StaffMember¶
-
class
StaffMember
¶ -
user
¶ Required
ForeignKey
User
The
User
to which this profile relates. Choices are limited to active users.
-
first_name
¶ CharField(150)
The first name of the user. It is automatically synced with the user object and is provided in this model for convenience.
-
last_name
¶ CharField(150)
The last name of the user. It is automatically synced with the user object and is provided in this model for convenience.
-
slug
¶ Required
SlugField
A URL-friendly version of the first and last name.
-
email
¶ EmailField
The email address of the user. It is automatically synced with the user object and is provided in this model for convenience.
-
bio
¶ TextField
An in-depth, riveting account of the user’s life.
-
is_active
¶ Required
BooleanField
Default:True
True
indicates a current staff member.False
indicates a former staff member.
-
phone
¶ PhoneNumberField
A series of digits which, when typed into telephonic devices, might establish a vocal connection to the user.
-
photo
¶ RemovableImageField
A visual, digital representation of the user. The image is stored based on the PHOTO_STORAGE setting.
-
photo_height
¶ IntegerField
An automatically-managed reference to the height of the uploaded photo.
-
photo_width
¶ IntegerField
An automatically-managed reference to the width of the uploaded photo.
-
twitter
¶ CharField(100)
The staff member’s Twitter ID
-
facebook
¶ CharField(100)
The staff member’s Facebook ID
-
google_plus
¶ CharField(100)
The staff member’s Google Plus account
-
website
¶ URLField
A custom web site for the staff member.
-
sites
¶ ManyToManyField
Site
The sites that the staff member works on.
-
get_full_name
()¶ A convenient way to concatenate the first and last name.
Returns: unicode
-