views
from django.forms.models import inlineformset_factory from djStock.stock.models import MyAModel from djStock.stock.forms.MyAModelForm import MyAModelForm from djStock.stock.models import MyBModel from djStock.stock.forms.MyBModelForm import MyBModelForm def a_create(request): form = MyAModelForm() formset_factory = inlineformset_factory(MyAModel, MyAModel.things.through) formset = formset_factory() [...] def b_create(request): form = MyBModelForm() formset_factory = inlineformset_factory(MyBModel, MyBModel.things.through) formset = formset_factory() [...]
(With this code, all work fine) So i made refactoring and write some class (i removed unecessary code for exemple):
ModelFormsetManager
from django.forms.models import inlineformset_factory class ModelFormsetManager(object): form = None formsets = {} def initialize_formset(self, name, entity, related_entity): self.formsets[name] = inlineformset_factory(entity, related_entity) # for debug at the end of question print self.formsets[name] def __init__(self, request, form_class): if request.method == 'POST': [...] else: self.form = form_class() for formset_name, formset in self.formsets.iteritems(): # for debug at the end of question print formset self.formsets[formset_name] = formset()
MyAModelManager
from ..models import MyAModel from ..forms.MyAModelForm import MyAModelForm from djStock.stock.managers.ModelFormsetManager import ModelFormsetManager class MyAModelManager(ModelFormsetManager): def __init__(self, request): self.initialize_formset('things', MyAModel, MyAModel.things.through) super(MyAModelManager, self).__init__(request, MyAModelForm)
MyBModelManager
from ..models import MyBModel from ..forms.MyBModelForm import MyBModelForm from djStock.stock.managers.ModelFormsetManager import ModelFormsetManager class MyBModelManager(ModelFormsetManager): def __init__(self, request): self.initialize_formset('things', MyBModel, MyBModel.references.through super(MyBModelManager, self).__init__(request, MyBModelForm)
With this refactoring my views look like:
def a_create(request): a_manager = MyAModelManager(request=request) [...] def b_create(request): b_manager = MyBModelManager(request=request) [...]
Okay, now the strange bug (keep in mind one thing: actions order is important):
Prints displays that:
<class 'django.forms.formsets.MyAModelThingFormFormSet'> <class 'django.forms.formsets.MyAModelThingFormFormSet'>
Prints displays that:
<class 'django.forms.formsets.MyBModelThingFormFormSet'> <class 'django.forms.formsets.MyBModelThingFormFormSet'>
And error is:
File "/home/bux/.python/envs/djStock/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/home/bux/Private/projets/djStock/stock/views/b.py", line 28, in b_create b_manager = MyBModelManager(request=request) File "/home/bux/Private/projets/djStock/../djStock/stock/managers/MyBModelManager.py", line 9, in __init__ super(MyBModelManager, self).__init__(request, MyBModelForm) File "/home/bux/Private/projets/djStock/../djStock/stock/managers/ModelFormsetManager.py", line 31, in __init__ self.formsets[formset_name] = formset() TypeError: 'MyAModelThingFormFormSet' object is not callable
Important note: At "formset()" django is trying to call My A ModelThingFormFormSet whereas My B ModelThingFormFormSet (print confirm it showing MyBModelThingFormFormSet). That's one of strange point.
If i reload b_create view, same error. If i reload a_create view it's always working.
I turn off python manage.py runserver |...] and run it again
I load b_create view (previously rasing error), now it's working.
Prints displays that:
<class 'django.forms.formsets.MyBModelThingFormFormSet'> <class 'django.forms.formsets.MyBModelThingFormFormSet'>
Prints displays that:
<class 'django.forms.formsets.MyAModelThingFormFormSet'> <class 'django.forms.formsets.MyAModelThingFormFormSet'>
And error is:
Traceback (most recent call last): File "/home/bux/.python/envs/djStock/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/home/bux/Private/projets/djStock/stock/views/stock.py", line 37, in a_create a_manager = MyAModelManager(request=request, form_initial=form_initial) File "/home/bux/Private/projets/djStock/../djStock/stock/managers/MyAModelManager.py", line 10, in __init__ super(MyAModelManager, self).__init__(request, MyAModelForm, form_initial=form_initial) File "/home/bux/Private/projets/djStock/../djStock/stock/managers/ModelFormsetManager.py", line 31, in __init__ self.formsets[formset_name] = formset() TypeError: 'MyBModelThingFormFormSet' object is not callable
We note again: the "not callable object" is related to the previous view! Not to current view.
So, to solve the problem i've change ModelFormsetManager to:from django.forms.models import inlineformset_factory class ModelFormsetManager(object): form = None formsets = {} formsets_factorys = {} def initialize_formset(self, name, entity, related_entity): self.formsets_factorys[name] = inlineformset_factory(entity, related_entity) # for debug at the end of question print self.formsets[name] def __init__(self, request, form_class): if request.method == 'POST': [...] else: self.form = form_class() for formset_name, formset in self.formsets_factorys.iteritems(): # for debug at the end of question print formset self.formsets[formset_name] = formset()
So i use different attribute to stock return of inlineformset_factory (formsets_factorys) and result of formset() (formsets). Know, i'm very, very curious to know why python/django mistake between to view.
Have a nice day!
Ps: English not my native language