Django模型:动态更改db_table [英] Django model: change db_table dynamically

查看:457
本文介绍了Django模型:动态更改db_table的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a large number of sets of data. Each set of data comprises of several database tables. The schema for the sets of database tables is identical. Each set of tables can have over a million rows. Each set of data belongs to one job, there are no relations between jobs. One or more jobs belong to a different user. Sets of tables get imported and eventually deleted as a set of tables. From a performance point of view it is better to keep them as separate sets of tables.

因此,我想为几个表中的每个表提供几个通用的Django模型。
我是通过使用类似于以下代码的在我的views.py文件中实现的:

So I would like to have several generic Django models one for each of the several tables. I have achieved it in my views.py file by using code similar to this:

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应用程序的并发多个用户一起使用是否安全?模型对象是否在用户之间共享?如果同时有两个请求,将会发生什么事?

My questions are: Is it safe to use this code with concurrent multiple users of a Django based web application? Are the models objects shared across users? What would happen if there were two requests simultaneously?

编辑NO 2:我考虑了李·赖安(Lie Ryan)的回答和评论,并提出了以下代码:

EDIT NO 2: I have considered Lie Ryan's answer and the comments and come up with this code:

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>')

现在我的问题是,此代码的第二稿在同时存在多个用户的情况下是否安全?

Now my question is, is this second draft of the edited code safe with concurrent multiple users?

推荐答案

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

This technique is called sharding. No, it is not safe to do this if you serve concurrent requests with threads.

您可以做的是动态构造指向不同db_tables的多个类,并使用工厂选择合适的类。

What you can do is to dynamically construct multiple classes pointing to different db_tables, and use a factory to select the right class.

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

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

And then create a function that selects the right table_map based on how you shard your data.

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

Also be careful of injection if you accept table name from user input.

或者,某些数据库系统(例如PostgrSQL)允许每个数据库使用多个架构,这在某些情况下可能是分离数据的更好方法

Alternatively, some database systems like PostgrSQL allows multiple schemas per database, which might be a better way to separate your data in certain circumstances.

这篇关于Django模型:动态更改db_table的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆