代码极思精致的瞬间(其一)

一,类型检查 与 request.data 配合使用!
Draft4Validator 定义了什么样的类型对应什么样的字段!比如 "type" "properties"(字典) "required"列表,只要是 post put 请求都加上
#from jsonschema import  validate

def json_schema_validate(schema):
    def valieated_func(func):
        def _func(self, request, *args, **kwargs):
            try:
                validate(request.data, schema)
            except ValidationError as e:
                raise_from(InvalidJsonException, e)
            else:
                return func(self, request, *args, **kwargs)
        return _func
    return valieated_func

@json_schema_validate({
    'type': 'object',
    'properties': {
        'user': {
            'type': 'string',
            'minLength': 1
        },
        'pass': {
            'type': 'string',
            'minLength': 1
        },
    },
})
def post(self, request):  # 前端传参!{"pass": "admin","user": "admin"}
    pass
View Code
二,项目运行流程:
1,数据的收集 是采用 slurm 运行结果存储到 文件之中 然后读取文件(多线程)
2,首先数据是存取到 influxdb 之中的。
3,使用 selery 定时任务, 从influx 往postgres 存取数据
4,api 数据是 大部分来自于 influx , 查询的是 最新的数据
5,由于大量的查询是来自于 influx 所以采用 django自带的缓存 来缓存查询!
三 ,NodeHistoryBaseView 的封装!
1,所有的都是根据 pk 值 进行查询的 查询某一个 id的 cpu 历史 gpu 历史 network历史等等!
2,所有的子类 继承 NodeHistoryBaseView必须 重写 get_db_table(因为父类制定了是抽象方法,子类不能实例化此方法)
3, 父类是抽象类
@add_metaclass(ABCMeta)
class NodeHistoryBaseView(APIView):

    TENDENCY_INTERVAL_TIME = {
        'hour': '30s',
        'day': '12m',
        'week': '1h24m',
        'month': '6h12m'
    }

    def get(self, request, pk, category):
        hostname = Node.objects.get(id=pk).hostname
        sql_history = self.get_history_sql(request, category, hostname)
        logger.info("sql: %s" % (sql_history,))
        try:
            history = cache.get(sql_history, epoch='s')
        except InfluxDBServerError or InfluxDBClientError:
            raise InfluxDBException
        history = self.handle_query_data(history)
        sql_current = self.get_current_sql(category, hostname)
        logger.info("sql: %s" % (sql_current,))
        current = self.get_current_data(sql_current)
        return self.return_success(history, current)

    @abstractmethod #父类制定了是抽象方法,子类不能实例化此方法
    def get_db_table(self):
        pass

    @property
    def get_scale_data(self):
        ''' sql: select [sql value] **
            handle_key: handle_query_data use handle_key'''
        return {'sql': 'last(value) as value', 'handle_key': ['value']}

    def get_history_sql(self, request, *args, **kwargs):
        category = args[0]
        hostname = args[1]
        sql = "select {field_sql} from \"{categ}\".{table} where \
         host=\'{host}\'".format(
                field_sql=self.get_scale_data['sql'],
                categ=category,
                table=self.get_db_table(),
                host=hostname)
        sql += " and time > now() - %s" % (CATEGORY_MAPPING[category],)
        sql += " group by time(%s)" % (self.TENDENCY_INTERVAL_TIME[category],)
        return sql

    def get_current_sql(self, category, hostname):
        sql = "select last(value) from \"{categ}\".{table} where " \
              "host=\'{host}\'".format(categ=category,
                                       table=self.get_db_table(),
                                       host=hostname
                                       )
        return sql

    def get_current_data(self, sql):
        ret = cache.get(sql)
        current = 0
        for p in ret.get_points():
            current = p.get('last', 0)
        return current

    def handle_query_data(self, data):
        return list(data.get_points())

    def return_success(self, history, current):
        return_data = {"history": history if history else [],
                       'current': current}
        return Response(return_data, status=HTTP_200_OK)
View Code
子类(视图)对抽象类的使用
class NodeHistoryCpuView(NodeHistoryBaseView):
    permission_classes = (AsOperatorRole,)

    def get_db_table(self):
        return 'node_cpu'
四,django 讲一个文件夹 中的文件压缩到另一个文件 api
import tarfile
import uuid
from glob import iglob
from os import path


class WebLogView(APIView):
    permission_classes = (AsAdminRole,)

    def post(self, request):
        #生成一个压缩文件名称
        target = path.join(
            settings.DOWNLOAD_DIR, 'lico-log-{}.tar.bz2'.format(uuid.uuid4())
        )

        with tarfile.open(target, 'w:bz2') as tf:
            # 遍历所有的 以 log 结尾的文件 并且进行压缩!
            # iglob() 遍历文件夹 返回的是生成器
            for f in iglob(
                path.join(settings.LOG_DIR, '*.log')
            ):
                tf.add(f, path.join('lico-log', path.basename(f)))
        # 只返回文件名称 不是路径
        return Response(
            data={'name': path.basename(target)}
        )
View Code

 

posted @ 2018-11-06 12:21  十七楼的羊  阅读(191)  评论(0编辑  收藏  举报