Admin¶
1. Redefine User Admin¶
In order to add more admin actions related to User object, we need to redefine the User Admin model.
Inline¶
model inline combines 2 model so that info from RegisterUser can be modified and displayed with user info
first, create a class for inline model in app/admin.py
class UserInline(admin.TabularInline):
model = RegisterUser
More info on RegisterUser model.
We need to redefine a UserAdmin
to do the modification. In list_display, we choose the field we want to see in admin page.
And add the action to actions
:
class UserAdmin(admin.ModelAdmin):
list_display = (
'username',
'email',
'first_name',
'last_name',
'department',
'organization',
'is_staff',
'date_joined',
)
inlines = [
UserInline,
]
actions = []
The two field department
and organization
are from RegisterUser model, and we cannot display them directly.
We will write them as callable or a string representing an attribute. See Django Documentation.
# callable that display info from RegisterUser
def department(self,user):
return "{}".format(RegisterUser.objects.get(user=user).department)
department.short_description = 'department'
def organization(self,user):
return "{}".format(RegisterUser.objects.get(user=user).organization)
organization.short_description = 'organization'
at last we unregister the previous User
model provided by Django and register our UserAdmin
model with the User
model.
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
For any action written for User, define the function before UserAdmin class.
2. Admin action of Send Email from Admin¶
Goal¶
Allow admin to send email to specific users. procedure:
- Log in as admin, and in the main page, go to Users.
- Using checkbox to choose recipient
- Select “Email Users“ in action
- Click “Go“ to direct to a web page for admin to input subject and message, and pass a list of user id through session.
Approach¶
We will add a new action to User admin called email user
to redirect the page to our admin_send_email
page, and pass the id of selected user to admin_send_email
page.
In app/admin.py
First we write the action. An admin action takes 3 parameters, self, request and queryset.
The queryset contains every user object we selected under User admin page.
def email_users(self, request, queryset):
list = queryset.values('email','id')
user_id_selected = []
for l in list:
user_id_selected.append(l['id'])
we will then use a “request.session](https://docs.djangoproject.com/en/1.11/topics/http/sessions/)“
to pass the email_selected
and redirect admin to admin_send_email
page:
#open a session and render the email_selected to admin_send_email view
request.session['user_id_selected'] = user_id_selected
return redirect('admin_send_email')
email_users.short_description = "Email Users"
Give this action a description shown in the action list when admin select actions. Note that it is called outside the function.
Add this function to actions
under UserAdmin model.
actions = [email_users]
3. Export User Data to CSV¶
Goal¶
To create an admin action that download a CSV file containing info of selected user(s).
UserAdmin class and Admin action¶
Django Documentation on “Outputting CSV with Django“
To see how to add actions to Model and how to modifyUserAdmin
,
see here.
Action Function¶
Go to app/admin.py
, find actions
in class UserAdmin
, add the new function export_csv
.
And create the function before class UserAdmin
:
def export_csv(modeladmin, request, queryset):
#setup csv writer
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment;filename=CAM2UserList.csv'
writer = csv.writer(response)
The CSV-creation acts on file-like objects such as the HttpResponse in Django.
See Django documentation.
opts = queryset.model._meta #obtaining User model as meta data because models are not iterable
required_field_names = [field.name for field in opts.fields] #get names of all fields in User model as a list
optional_field_names = [field.name for field in RegisterUser._meta.fields] ##get names of all fields in User model as a list
We need to seperate them because they will be used for every iteration of selected users. And create another combined list for the final CSV form.
field_names = required_field_names.copy()
for field in optional_field_names:
field_names.append(field)
writer.writerow(field_names)
To obtain info of each user, an for loop is used, and the required info and optional info will be gained through each iteration.
The field in required_field_names
and optional_field_names
decide which info from User
and RegisterUser
model we will get.
More info on RegisterUser
, see here.
for obj in queryset:
required_info = [getattr(obj, field) for field in required_field_names]
try:
optional = RegisterUser.objects.get(user=obj) # get optional info of user
optional_info = [getattr(optional, field) for field in optional_field_names]
except:
optional_info = ['N/A' for field in optional_field_names]
for data in optional_info:
required_info.append(data)
writer.writerow(required_info)
return response
Give this action a name outside function(no indentation):
export_csv.short_description = "Export selected user as csv"
Add this function to actions
under UserAdmin model.
actions = [email_users, export_csv]