Django中利用type动态操作数据库表
场景分析:
后台MySql数据库保存了一大批按股票代码命名的数据表,每张表保存的是每只股票的日线数据。
stock_000002
stock_600030
stock_600020
...一共3000多个表。
Django中如果要按股票代码展示每张表的数据,利用常规ORM模型变得非常困难,因为有3000多个表,就需要建3000多个模型。
解决办法:
1. 根据表名、字段等动态创建ORM表模型
def create_model(name, fields=None, app_label='', module='', options=None, admin=None): class Meta: pass if app_label: setattr(Meta, 'app_label', app_label) if options is not None: for key, value in options.items(): setattr(Meta, key, value) attrs = {'__module__': module, 'Meta': Meta} if fields: attrs.update(fields) # 继承models.Model return type(name, (models.Model,), attrs)
2. 调用create_model, 返回的custom_model就是表对应的ORM模型
def new_stock(tab_name): """ 动态创建数据模型 :param tab_name: 表名 :return: 返回模型类 """ fields = { 'ts_code': models.CharField(max_length=20), 'trade_date': models.CharField(max_length=20, unique=True), 'open': models.FloatField(null=False, default=0.0), 'high': models.FloatField(null=False, default=0.0), 'low': models.FloatField(null=False, default=0.0), 'close': models.FloatField(null=False, default=0.0), 'pre_close': models.FloatField(null=False, default=0.0), 'change': models.FloatField(null=False, default=0.0), 'pct_chg': models.FloatField(null=False, default=0.0), 'vol': models.FloatField(null=False, default=0.0), 'amount': models.FloatField(null=False, default=0.0) } options = {'ordering': ['trade_date'], 'db_table': tab_name, } custom_model = create_model(tab_name, fields, options=options, app_label='stock', module='stock.models') return custom_model
3. http请求按日期降序排列的股票日线数据。
def stock_detail(request, pk): tab_name = 'stock_' + pk stock_mod = new_stock(tab_name) # 查询 if request.method == 'GET': limit = request.GET.get('limit') offset = request.GET.get('offset') # 查询总记录条数 total = stock_mod.objects.count() # 结果按日期降序排列 datalist = stock_mod.objects.all().order_by('-trade_date')[int(offset): int(offset)+int(limit)] json_list = [] import json # 返回json字符串 for data in datalist: json_dict = model_to_dict(data) json_list.append(json_dict) result = dict() rows = list() result['total'] = total result['rows'] = json_list logger.info('获取股票列表') return JsonResponse(result, safe=False)
HTTP请求:GET /stock/000002/?offset=0&limit=10
000002与"stock_"组合成表名"stock_000002"
offset为数据的起始位置
limit为返回数据的条数
按表查询得到的datalist数据组织成json格式返回浏览器。