最近刚好需要使用到消息队列,与rabbitmq比较之后,发现redis更容易上手。虽然比起redis,rabbitmq对消息队列的功能支持更强大;而且redis不比rabbitmq——默认自带消息队列的管理后台。所以,我这里使用Django的xadmin进行了改造,来作为redis一个简单的消息队列可视化管理。效果如下图:
由于默认的xadmin功能是对数据库里的数据进行显示,所以这里需要进行一些自定义修改。xadmin一般默认是MySQL进行对接,将表里的数据在页面上显示出来。所以我原本的思路是,修改对models的查询结果,将xadmin从mysql查询的数据改到从redis查询。但通过查看源码发现,xadmin的前端显示与后端返回的queryset对象进行了绑定,通过遍历queryset对象的属性来获取查询数据的,很难找到在中间修改数据源的位置。所以这里是直接重写了部分前端代码。
为了支持功能的扩展,这里的消息获取使用drf的APIView接口:
class MsgQueueAPI(APIView):def post(self, request):conn = redis.StrictRedis()res = conn.zrange("task", 0, -1)return HttpResponse('{"status":"success","res":' + json.dumps(res, ensure_ascii=False) + '}',content_type="application/json")
这里从redis的有序集合中获取所有的消息,以json的形式返回到前端。为了将消息整合到xadmin中显示,需要新增一个models:
class Queue(models.Model):msg = models.CharField(max_length=10, verbose_name=u"队列消息", default=u"", null=True, blank=True)class Meta:db_table = "msg_queue"verbose_name = u"消息"verbose_name_plural = verbose_namedef __unicode__(self):return u"消息"
这里的models只有一个字段,但由于后面对前端的显示进行了自定义改造,所以这里的字段、包括数据库里的数据没有什么意义,只是为了xadmin上的显示。接下来,要对关联models的adminx进行一些特殊处理:
class QueueAdmin(object):msg = Truelist_display = ['msg']search_fields = []list_filter = []list_export = ()list_exclude = ['id']def save_models(self):msg = self.new_obj.msgconn = redis.StrictRedis()conn.zadd("task", time.time(), msg)xadmin.site.register(Queue, QueueAdmin)
xadmin.site.register_plugin(MsgQueuePlugin, ListAdminView)
先说说从list_display向下的一些属性,是为了移除一些管理界面上用不到的功能,如过滤器、搜索框、导出数据功能等;这里要注意的是save_models方法,它重写了原来向MySQL数据的功能,通过new_obj先获取到增加数据界面提交的内容,但是不往MySQL里保存,而是向redis的队列里插入消息内容。通过save_models方法的特性,执行完该方法后,会自动跳转到列表显示页面。接下来要做的,就是在列表显示页面加载时调用上面写的MsgQueueAPI读取消息。
新建一个msgQueue.js文件,并在加载时向MsgQueueAPI接口发送ajax请求。然后通过xadmin的自定义插件来加载js文件:
class MsgQueuePlugin(BaseAdminPlugin):msg = Falsedef init_request(self, *args, **kwargs):return bool(self.msg)def get_media(self, media):media.add_js([self.static('js/jquery.min.js'),self.static('js/ajaxSetup.js'),self.static('js/jquery.COOKIE.js'),self.static('js/sendAjax.js'),self.static('js/msgQueue.js')])return media
这里已经在第三个代码片段通过xadmin.site.register_plugin的方式加载了该插件,并在QueueAdmin中配置msg为True使插件生效。在MsgQueuePlugin插件中可以看到,重写了get_media方法并加载了我们刚刚创建的msgQueue.js文件。
最后记得,js获取到请求数据后,通过jquery修改xadmin原有页面的部分html结构,将消息显示出来。这里只是做了简单的消息展示。通过前端的js,其实我们还可以做更多的事情,比如消息的删除,指定需要发布到哪个消息队列等。