Bug: Manually changing "_meta.db_table" for model causes "missing FROM-clause entry for table" error

203 views
Skip to first unread message

evil...@gmail.com

unread,
Nov 13, 2015, 1:40:21 PM11/13/15
to Django users
Hello.
I've got the same model in two projects and want to copy data from one to another using model meta 'db_table' option:


my_model_original_table_name = MyModel._meta.db_table
MyModel._meta.db_table = 'old_project_table_name'

old_objects = MyModel.objects.using('old_project_data_base').values('name')
old_objects = list(old_objects)

MyModel._meta.db_table = my_model_original_table_name

for old_object in old_objects:
    new_object, created = MyModel.objects.update_or_create(name=old_object['name'])


Old data retrieving works great, but when i try to execute last statement i get:
"django.db.utils.ProgrammingError: missing FROM-clause entry for table "old_project_table_name""

I tied to fetch data at the last stage instead of updating/creating (MyModel.objects.all()) and get the same error.
The sql-query created by ORM is:
SELECT "old_project_table_name"."name" FROM "new_project_table_name"

Why is it so?

I am using django 1.8.6 and PostgreSQL 9.4.5
Django 1.7.* work fine.


Thanks!

Tim Graham

unread,
Nov 14, 2015, 9:59:51 AM11/14/15
to Django users
I'm not sure that type of monkeypatching of Model._meta.db_table is meant to be supported. You could try to bisect Django's commit history to find the commit that changed the behavior. My guess it that it might have to do with some internal caching such that your monkeypatch no longer has any effect.
Message has been deleted

evil...@gmail.com

unread,
Nov 15, 2015, 3:04:48 AM11/15/15
to Django users
Thanks for the answer.
What do you suggest to use instead of this ugly method, raw sql?

James Schneider

unread,
Nov 15, 2015, 4:33:28 PM11/15/15
to django...@googlegroups.com
On Sun, Nov 15, 2015 at 12:04 AM, <evil...@gmail.com> wrote:
Thanks for the answer.
What do you suggest to use instead of this ugly method, raw sql?

Would it make sense to serialize a ModelDatabaseA object (perhaps into JSON or a standard Python dict) and use that to populate/create a ModelDatabaseB object, so that all of the references to the original database would be stripped away? Maybe even use a ModelDatabaseA object directly as an argument in a class method to return a ModelDatabaseB object. You could then implement a custom DB router to make sure that all queries for ModelDatabaseB would go to/from your second database? 


To me, this would be a preferred method over mangling the internal _meta information. It would also give you more control over what fields are transferred, say if ModelDatabaseB was only a subset of ModelDatabaseA. 

-James

Kalvin Handilist

unread,
Jul 13, 2017, 1:39:15 PM7/13/17
to Django users
Hi I encounter same problem as your, do you already got the solution? Any help will be appreciated, thank you~

Guilherme Leal

unread,
Jul 13, 2017, 2:04:06 PM7/13/17
to django...@googlegroups.com
I don't think that sould be possible to change real table name "on the fly". If I'm not mistaken, that kind of attribute is used by model's meta class during class creation process to populate the django model cache, which in turn only occurs during the django configuration step.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/0b3e71a1-ac34-459b-a2b0-32086492077d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages