Django (cache?) make some mistake with formset generated class

84 views
Skip to first unread message

Bastien Sevajol

unread,
Nov 7, 2013, 5:54:02 AM11/7/13
to django...@googlegroups.com
Hello, i don't know if it's a django or python problem. But i correct a strange bug and would know why my code was bugging and if it was django, python, or me. The situation (and solution) is exposed here but i reproduce it here:

I've two page, each of one display a form and a formset. They have same code logic:

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

  • When i load a_create view, all is displayed correctly (reloading page to).

Prints displays that:

<class 'django.forms.formsets.MyAModelThingFormFormSet'>
<class 'django.forms.formsets.MyAModelThingFormFormSet'>
  • I load b_create view, an error raised.

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'>
  • I load a_create view (previously working), now it is not working.

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


Simone Federici

unread,
Nov 7, 2013, 8:45:45 AM11/7/13
to django...@googlegroups.com

On Thu, Nov 7, 2013 at 11:54 AM, Bastien Sevajol <sevajol...@gmail.com> wrote:
formsets = {}

this class variable is in ModelFormsetManager class namespace
so it is shared across the subclasses.

You are using formsets to save before the object class, and after the instances,
so when in the formset there is the instance of the last "view", and you try to call it
create the instance of an class works, call the instance return object is not callable exception

your last solution solve only apparently the superclass-namespace issue.


regards

Bastien Sevajol

unread,
Nov 8, 2013, 2:50:18 AM11/8/13
to django...@googlegroups.com
You're right! I mistake with python object logic :/ Sorry !
Thank's !
Reply all
Reply to author
Forward
0 new messages