【问题标题】:Django model: change db_table dynamicallyDjango 模型:动态更改 db_table
【发布时间】:2014-08-26 06:29:09
【问题描述】:

我有大量的数据集。每组数据由几个数据库表组成。数据库表集的架构是相同的。每组表可以有超过一百万行。每组数据属于一个工作,工作之间没有关系。一个或多个作业属于不同的用户。表集被导入并最终作为一组表被删除。从性能的角度来看,最好将它们保留为单独的表集。

所以我想为几个表中的每一个提供几个通用的 Django 模型。 我已经在我的views.py 文件中通过使用类似这样的代码实现了它:

from foobar.models import Foo, Bar

def my_view(request):
  prefix = request.GET.get('prefix')
  Foo._meta.db_table = prefix + '_foo'
  Bar._meta.db_table = prefix + '_bar'
  ....

  foobar_list = Foo.objects.filter(bar_id=myval)
  ...

我的问题是:将这段代码用于基于 Django 的 Web 应用程序的并发多个用户是否安全?模型对象是否在用户之间共享?如果同时有两个请求会怎样?

编辑 NO 2:我已经考虑了 Lie Ryan 的答案和 cmets 并提出了以下代码:

from django.http import HttpResponse, HttpResponseNotFound
from django.db import models
from django.template import RequestContext, loader

def getModels(prefix):
    table_map = {}

    table_map["foo"] = type(str(prefix + '_foo'), (models.Model,), {
        '__module__': 'foobar.models',
        'id' : models.IntegerField(primary_key=True),
        'foo' : models.TextField(blank=True),
        })
    table_map["foo"]._meta.db_table = prefix + '_foo'

    table_map["bar"] = type(str(prefix + '_bar'), (models.Model,), {
        '__module__': 'foobar.models',
        'id' : models.IntegerField(primary_key=True), 
        'foo' : models.ForeignKey(prefix + '_foo', null=True, blank=True),
        })
    table_map["bar"]._meta.db_table = prefix + '_bar'

    return table_map

def foobar_view(request):  
    prefix = request.GET.get('prefix')
    if prefix != None and prefix.isdigit():
        table_map = getModels(prefix)
        foobar_list = table_map["bar"].objects.filter.order_by('foo__foo')
        template = loader.get_template('foobar/foobar.html')
        context = RequestContext(request, {
            'foobar_list': foobar_list,
        })
        return HttpResponse(template.render(context))
    else:
        return HttpResponseNotFound('<h1>Page not found</h1>')

现在我的问题是,编辑后的代码的第二稿对于并发多个用户是否安全?

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    这种技术称为分片。不,如果您使用线程处理并发请求,这样做是不安全的。

    你可以做的是动态构造多个指向不同db_tables的类,并使用工厂来选择正确的类。

    tables = ["foo", "bar"]
    table_map = {}
    for tbl in tables:
        class T(models.Model):
            db_table = tbl
            ... table definition ...
        table_map[tbl] = T
    

    然后创建一个函数,根据您的数据分片方式选择正确的 table_map。

    如果你接受用户输入的表名,也要小心注入。

    另外,一些数据库系统(如 PostgrSQL)允许每个数据库有多个模式,这可能是在某些情况下分离数据的更好方法。

    【讨论】:

    • @Dan-Dev:应该可以动态设置db_table,只要你每次都创建一个新类。尝试使用类型构造函数实例化一个新类,例如type('ClassName', models.Model, dict)。但是,拥有数万组表可能是错误的架构。为什么需要这样的东西?
    • 我已更新问题以反映我认为您在说什么。如果我错了,你能纠正我吗?
    • 或者建议是否可以。这是一个自动化测试服务,我希望成千上万的用户分布在多个 Django 安装中。
    • 看了你的评论后我再次更新了问题希望我已经正确理解你并且解决方案很好。
    • 在这种情况下,表格 - foobar - 必须提前知道并且不能即时添加表格?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 2013-08-04
    • 2021-02-04
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多