Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single Django model, multiple tables?

I know this exact same question has been previously asked, but I was hoping for a 'better' answer (that does not involve modifying class attributes at runtime). This was the question:

Single Django model, multiple tables?

I have the same problem - I am looking for a solution similar to the responder's first reply, but that actually works. If there is no better solution, can anyone comment on how reliable the responder's solution is? It seems to me that the delay between changing the database name and querying the database could end up returning results from the wrong table:

query 1: change the name

query 2: change the name again

query 1: get results (but using the incorrect name from query 2)

Edit: The model is intended for use on ~15 tables - so inheritance is impractical, since it would require a new model name every time.

Thanks

P.S. My apologies if this is not the correct way of asking for an elaboration on a question.

like image 736
user908085 Avatar asked Aug 23 '11 19:08

user908085


1 Answers

for a dynamic table and database interhangeable model with a more sexy behaviour than the one in your linked question you may use simple methods or properties:

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

You may try something like this...

The copy part is to avoid danger of shared options between models. It took me time to find this part of the solution. but for the rest it looks sexy and straightforward.

Of course once in python code you may use

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")
like image 150
christophe31 Avatar answered Nov 17 '22 22:11

christophe31