simpleui layer 自动更新数据并且在migrate时layer不自动加载
前言
这个问题应该不会有很多同学遇到,但是如果遇到了可以参考解决。
当你使用simpleui layer 时肯定会遇到更新了数据库数据后,layer中的数据并没有自动更新的情况。而当你更新解决完数据自动更新之后,很有可能会引出另一个问题,当模型结构发生变更时,恰好自动更新layer的时候需要依赖这个模型,嘿嘿,那你就会在migrate的时候报错,类似:
django.db.utils.OperationalError: (1054, "Unknown column 'assets_DomainList.cloud_certificate_id' in 'field list'")
一 自动更新layer数据
通过admin_action装饰器将layer所需要的属性都进行赋值。
1 生成layer
1.1 按钮
@admin_action(short_description='导入域名列表', _type='success', icon='el-icon-s-promotion', layer=ImportDomainListLayer()()) def import_domain_list(self, request, queryset): return JsonResponse(data={ 'status': 'success', 'msg': '处理成功!' })
1.2 layer装饰器
def admin_action(short_description=None, icon=None, _type=None, confirm=None, style=None, layer=None): """ 后台action属性装饰器 :param layer: :param style: :param short_description: :param icon: :param _type: :param confirm: :return: """ def decorator(func): func.short_description = short_description func.icon = icon func.type = _type func.confirm = confirm func.style = style func.layer = layer @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper return decorator
1.3 合成layer的类
class ImportDomainListLayer: def __init__(self): self.layer = { 'title': '导入域名和记录', 'tips': '清空之后重新导入,不同凭证对应不同的平台。', 'confirm_button': '确认提交', 'cancel_button': '取消', 'width': '40%', 'labelWidth': "80px", 'params': [] } self.dst_cloud_select = { 'type': 'select', 'key': 'dst_cloud', 'label': '目标云平台凭证', 'size': 'small', 'options': [] } def generate_layer(self): self.dst_cloud_select['options'] = [{'key': cc.id, 'label': cc.name} for cc in CloudCertificate.objects.all()] self.layer['params'] = [ self.dst_cloud_select, ] return self.layer @admin_layer_load def __call__(self, *args, **kwargs): return self.generate_layer()
2 自动更新layer数据
通过信号在依赖的模型每次新增数据后自动刷新layer属性数据。
2.1 信号函数
@receiver(post_delete, sender=CloudCertificate, dispatch_uid='post_delete_CloudCertificate') def del_import_domain_list_layer(sender, **kwargs): logger.info("CloudCertificate del 触发信号。") DomainListMixins.import_domain_list.layer = ImportDomainListLayer()()
二 在migrate时layer不自动加载
思路就是在migrate的时候忽略掉layer的加载。
1 控制不加载的装饰器
def admin_layer_load(func): """ 在migrate模式下,不加载layer :param func: :return: """ @wraps(func) def wrapper(*args, **kwargs): return 'pass' if 'migrate' in sys.argv else func(*args, **kwargs) return wrapper
2 在调用layer的时候加入判断
@admin_layer_load def __call__(self, *args, **kwargs): return self.generate_layer()
要是大佬们有更好的解决办法,可以留言赐教。