Одна модель Django, несколько таблиц? - PullRequest
7 голосов
/ 23 августа 2011

Я знаю, что этот же вопрос уже задавался ранее, но я надеялся на «лучший» ответ (который не включает изменение атрибутов класса во время выполнения).Это был вопрос:

Одиночная модель Django, несколько таблиц?

У меня та же проблема - я ищу решение, подобное первому ответу респондента, ноэто на самом деле работает.Если нет лучшего решения, может ли кто-нибудь прокомментировать, насколько надежно решение респондента?Мне кажется, что задержка между изменением имени базы данных и запросом базы данных может привести к тому, что результаты будут возвращены из неверной таблицы:

запрос 1: изменить имя

запрос 2: изменить имяснова

запрос 1: получить результаты (но с использованием неверного имени из запроса 2)

Редактировать: модель предназначена для использования в ~ 15 таблицах - поэтому наследование нецелесообразно, поскольку для этого потребуетсякаждый раз новое название модели.

Спасибо

PS Приношу свои извинения, если это неправильный способ задать вопрос по вопросу.

Ответы [ 2 ]

2 голосов
/ 24 августа 2011

для динамически изменяемой модели таблиц и баз данных с более сексуальным поведением, чем в вашем связанном вопросе, вы можете использовать простые методы или свойства:

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")
0 голосов
/ 19 сентября 2018

Очень полезный фрагмент.

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