python - Multiple fields to the same DB column -


we trying speed our app prefetch_related. can follow genericforeignkey relations, , can go deeper __ unfortunately fail if related model not have such field.

here example of model structure

class modela(models.model):     event_object = models.foreignkey(somemodela)  class modelb(models.model):     event = models.foreignkey(somemodelb)  class modelc(models.model):     content_type = models.foreignkey(contenttype)     object_id = models.positiveintegerfield()     content_object = generic.genericforeignkey() 

so modelc instance can point either modela or modelb. , can use such queryset prefetch both , b models: modelc.objects.all().prefetch_related('content_object') unfortunately need select event object (somemodela or somemodelb)

if try run

modelc.objects.all().prefetch_related('content_object', 'content_object__event_object') 

it work if have modelc instances points modela, in ohter case fail because modelb not have event_object field , have event instead.

this models used in many places across code it's not idea rename field. wonder if there way create alias field/column.

i trying this:

class modelb(models.model):     event = models.foreignkey(somemodelb)     event_object = models.foreignkey(somemodelb, db_column='event_id', related_name='+') 

to make 2 fields point same column in db table. not working breaks save method. django creates update sql query 1 column placed twice , gets databaseerror

is there way create such alias? or maybe there solution make prefetch_related not throw exception?

update: in save method there update_fields parameter can used exclude field. introduced in 1.5 , using 1.4. continue search answer.

update #2: @shx2 asked me provide traceback. there 2 possible traceback. 1st - when attribute missing on first object:

traceback (most recent call last):   file "<console>", line 1, in <module>   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 72, in __repr__     data = list(self[:repr_output_size + 1])   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 97, in __iter__     len(self)   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 89, in __len__     self._prefetch_related_objects()   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 570, in _prefetch_related_objects     prefetch_related_objects(self._result_cache, self._prefetch_related_lookups)   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 1664, in prefetch_related_objects     (attr, first_obj.__class__.__name__, lookup)) attributeerror: cannot find 'event_object' on modelb object, 'content_object__event_object' invalid parameter prefetch_related() 

and if prefetch_related parameters valid first object 2nd traceback:

traceback (most recent call last):   file "<console>", line 1, in <module>   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 72, in __repr__     data = list(self[:repr_output_size + 1])   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 97, in __iter__     len(self)   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 89, in __len__     self._prefetch_related_objects()   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 570, in _prefetch_related_objects     prefetch_related_objects(self._result_cache, self._prefetch_related_lookups)   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 1680, in prefetch_related_objects     obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)   file "/home/igor/workspace/projectname/eggs/django-1.4.2-py2.7.egg/django/db/models/query.py", line 1803, in prefetch_one_level     qs = getattr(obj, attname).all() attributeerror: 'modelb' object has no attribute 'event_object' 

it looks bug or oversight in django. workaround, can try defining custom manager 2-stage prefetching.

from django.db import models django.db.models import q django.contrib.contenttypes.models import contenttype  class prefetchworkaroundmanager(models.manager):     def get_queryset(self):         q = super(prefetchworkaroundmanager, self).get_queryset()         content_typea = contenttype.objects.get_for_model(modela)         content_typeb = contenttype.objects.get_for_model(modelb)         return q.filter(content_type__pk = content_typea.id).prefetch_related('content_object', 'content_object__event_object') | \                q.filter(content_type__pk = content_typeb.id).prefetch_related('content_object', 'content_object__event')  class modelc(models.model):     ...      objects_prefetched = prefetchworkaroundmanager() 

each caller wants prefetching take place should access modelc.objects_prefetched instead of modelc.objects:

modelc.objects_prefetched.filter(...) 

i admit, didn't test it, doesn't work as-is. believe approach sound.


Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

android - Keyboard hides my half of edit-text and button below it even in scroll view -

css - Make div keyboard-scrollable in jQuery Mobile? -