最近使用DjangoAdmin做了个管理后台,并在model列表界面添加自定义的按钮操作。由于做项目才开始接触Django,作为Django新手,中间趟过不少坑,整理成文以纪念之。
1.系统概述
管理后台采用Django-simpleui进行界面美化,效果还算满意,Django-simplueui的使用和搭建,可以参看simpleui官网上的demo案例。为了避免simpleui版本的演进,影响功能,我把simpleui库clone到本地后,加载到项目中,具体方法在simpleui的使用指南上都有,这里也不再赘述。
系统中添加按钮控件和操作的表涉及的表有三个:用户表、设备表、绑定表。为了方便后台管理员的操作,需要在设备model的显示页面上每一行后面添加下拉列表显示和选择用户,并添加绑定/解绑按钮来进行绑定和解绑操作。
2.添加自定义按钮功能
2.1 系统搭建和model显示配置
这个过程请参考simpleui的使用指南,确保管理后台运行和显示正常。
2.2 修改设备model
因为是在设备model的显示界面添加按钮,所以需要在models.py中修改设备model。
......
class Device(models.Model):
device_uuid = models.IntegerField(primary_key=True)
device_name = models.CharField(max_length=64)
......
def __str__(self):
return self.device_name
#添加用户列,没有绑定时显示下拉列表,供选择绑定用户
def binder(self):
try:
userbind = UserBind.objects.get(device_uuid=self.device_uuid)
#设备已经绑定,显示绑定用户
if userbind:
return userbind.user_name
else:
users = User.objects.all()
if not users:
return "没有用户"
#设备没有绑定时,显示用户下拉列表,多个设备时,页面会出现多个下拉列表,每个下拉列表的id需要跟device_uuid关联,
#便于js中找对应关系
select_str = '<select id="user_{}"> '.format(self.device_uuid)
for user in users:
select_str = select_str + '<option value="{}">{}</option> '.format(user.username, user.username)
select_str.join('</select>')
return format_html(select_str)
except:
users = User.objects.all()
if not users:
return "没有用户"
select_str = '<select id="user_{}"> '.format(self.device_uuid)
for user in users:
select_str = select_str + '<option value="{}">{}</option> '.format(user.username, user.username)
select_str.join('</select>')
return format_html(select_str)
binder.short_description = '所有人'
#添加绑定/解绑按钮
def op_binding(self):
#已绑定,显示解绑按钮
if self.is_bind == 1:
userbind = UserBind.objects.get(device_uuid=self.device_uuid)
#解绑操作的js函数需要传入两个参数,调用时涉及单引号和双引号的使用,
#只能分开写好各个字段后,再串接
paras = '"{}","{}"'.format(userbind.user_name, str(self.device_uuid))
cjs = "'javascript:unbinding(" + paras + ")'"
btn_str = '<input name="解绑" onclick=' + cjs + 'type="button" id="btn_deassign" ' + 'value="解绑">'
return format_html(btn_str)
#未绑定,显示绑定按钮
else:
btn_str = '<input name="绑定" onclick="javascript:binding({})" ' \
'type="button" id="btn_assign_{}" ' \
'value="绑定">'.format(self.device_uuid, self.device_uuid)
return format_html(btn_str)
op_binding.short_description = '绑定操作'
2.3编写js函数
设备的绑定/解绑操作通过在按钮的onclick事件中,调用js函数来实现。编写devicemode.js文件,并把js文件放入simpleui库的static\admin\js\admin\目录。
//binding函数传入device_uuid,并根据device_uuid找到对应的下拉列表取值
function binding(device_uuid){
var element_id = "user_" + String(device_uuid);
var username = document.getElementById(element_id).value;
var url = "/bind?username="+username+"&device_uuid="+String(device_uuid);
var Http = new XMLHttpRequest();
Http.open("GET", url);
Http.send();
setTimeout('location.reload()',100);
}
//unbinding函数传入username和device_uuid两个参数,直接解绑
function unbinding(username, device_uuid){
var url = "/unbind?username="+username+"&device_uuid="+String(device_uuid);
var Http = new XMLHttpRequest();
Http.open("GET", url);
Http.send();
setTimeout('location.reload()',100);
}
2.4 引用自定义js
在admin.py的Device配置中引用自定义的js。
......
@admin.register(Device)
class ApiAdmin(admin.ModelAdmin):
......
class Media:
js = ('admin/js/admin/devicemode.js',)
2.5 编写绑定/解绑接口
编写具体的绑定/解绑接口,并在urls.py中添加定义,供js调用。
urlpatterns = [
......
url(r'^bind', deviceapi.device_bind),
url(r'^unbind', deviceapi.device_unbind),
......
]
这样,自定义的按钮和功能就添加好啦!
3.参考资料
https://simpleui.88cto.com
https://simpleui.88cto.com/docs/simpleui/quick.html