我知道之前已经问过这个完全相同的问题,但我希望得到一个“更好”的答案(不涉及在运行时修改类属性)。这就是问题:
Single Django model, multiple tables?
我有同样的问题 - 我正在寻找类似于响应者的第一个回复的解决方案,但这确实有效。如果没有更好的解决方案,那么有人可以评论响应者解决方案的可靠性吗?在我看来,更改数据库名称和查询数据库之间的延迟可能最终从错误的表返回结果:
查询1:更改名称
查询2:再次更改名称
查询1:获取结果(但使用查询2中的错误名称)
编辑:该模型适用于~15个表 - 因此继承是不切实际的,因为每次都需要一个新的模型名称。
由于
P.S。如果这不是要求对问题进行详细阐述的正确方法,我表示歉意。
答案 0 :(得分:2)
对于动态表和数据库可交换模型,其行为比链接问题中的行为更性感,您可以使用简单的方法或属性:
import copy
class MyModel(models.Model):
# anything
@property
def table_name(self):
return self._meta.db_table
@table_name.setter
def table_name(self, value):
new_meta = copy.copy(self._meta)
new_meta.db_table = value
self._meta = new_meta
@classmethod
def set_qs_for_table(cls, qs, table):
my_class = copy.copy(cls)
my_options = copy.copy(my_class._meta)
my_class._meta = my_options
qs.model = my_class
您可以尝试这样的事情......
复制部分是为了避免模型之间共享选项的危险。我花了很长时间才找到解决方案的这一部分。但对于其余部分,它看起来很性感和直截了当。
当然,在python代码中,您可以使用
qs = MyClass.objects.all()
MyClass.set_qs_for_table(qs, "this_table")
my_instance = qs[0]
my_instance.table_name = "that_table"
my_instance.save(using="this_db")
答案 1 :(得分:0)
一个非常有用的代码段。
from django.db import models
shard_tables = {}
class ShardMixin():
@classmethod
def shard(cls, id=None):
def get_ext(id): # the multi tables rule
return str(id % 100)
ext = get_ext(id)
_db_table = "%s%s" % (cls._meta.db_table , ext) # your table name
if _db_table not in shard_tables:
class Meta:
db_table = _db_table
attrs = {
'__module__': cls.__module__,
'Meta': Meta,
}
shard_tables[_db_table] = type("%s%s" % (cls.__name__, ext), (cls, ), attrs)
return shard_tables[_db_table]
class User(models.Model, ShardMixin):
username = models.CharField(max_length=255, verbose_name=" username")
class Meta:
abstract = True
db_table = "user_"
users = User.shard(id=3).objects.values()
print(users)