Hello everybody,
This snippet is working fine, i used this instead of adding custom
arguments when overloading each of my ModelForm's constructore to keep
the same __init__() signature.
http://www.djangosnippets.org/snippets/1272/
Currently refactoring, it makes sense to use a factory in my case.
I tryed to copy the pattern of forms.model.modelform_factory, but now
it seems that my __init__() method is not overloading ModelForm
anymore
Recall the code of forms.model.modelform_factory:
/trunk/django/forms/models.py
326 def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
327 formfield_callback=lambda f: f.formfield()):
328 # HACK: we should be able to construct a ModelForm without creating
329 # and passing in a temporary inner class
330 class Meta:
331 pass
332 setattr(Meta, 'model', model)
333 setattr(Meta, 'fields', fields)
334 setattr(Meta, 'exclude', exclude)
335 class_name = model.__name__ + 'Form'
336 return ModelFormMetaclass(class_name, (form,), {'Meta': Meta,
337 'formfield_callback': formfield_callback})
That's what i'm actually trying to do:
# todo : get a more descriptive FC prefix than "jpic"
class JpicModelFormMetaclass(ModelFormMetaclass):
"""
Inherit from this, then use this new keyword argument
'jpic_field_options' with a dict of dicts such as:
{
'field_name_that_is_m2m': {
'queryset': aqueryset,
},
'field_name_that_is_fk': {
'queryset': anotherqueryset,
},
}
This solves the problem of using a queryset made in the view
as choices for a M2M/FK field ...
"""
def __init__(self, *args, **kwargs):
jpic_field_options = False
if 'jpic_field_options' in kwargs.keys():
jpic_field_options = kwargs.pop('jpic_field_options')
super(JpicModelFormMetaclass, self).__init__(*args, **kwargs)
if not jpic_field_options:
return
for field, args in jpic_field_options.items():
if field not in self.fields:
continue
for arg, value in args.items():
setattr(self.fields[field], arg, value)
class JpicModelForm(ModelForm):
__metaclass__ = JpicModelFormMetaclass
This is how i tryed to copy the factory method to use my metaclass:
def get_form_class(self):
# HACK: we should be able to construct a ModelForm without creating
# and passing in a temporary inner class
class Meta:
pass
setattr(Meta, 'model', self.model_class)
setattr(Meta, 'fields', self.get_fields())
if Group.objects.get(name='Consultants') in
self.request.user.groups.all():
class_name = self.model_class_name + 'ConsultantForm'
else:
class_name = self.model_class_name + 'ClientForm'
return JpicModelFormMetaclass(class_name.encode(),
(JpicModelForm,), {'Meta': Meta,
'formfield_callback': lambda
f: f.formfield()})
This error is thrown:
Traceback:
File "/home/python/libs/django/core/handlers/base.py" in get_response
86. response = callback(request, *callback_args,
**callback_kwargs)
File "/home/jpic/sites/devangels/django_tickets/views.py" in root
54. return view_class().root(request, url, action, dest_class)
File "/home/jpic/sites/devangels/django_tickets/views.py" in root
210. self.formobj = self.get_form()
File "/home/jpic/sites/devangels/django_tickets/views.py" in get_form
97. form = form_class(instance=self.model,
jpic_field_options=options)
Exception Type: TypeError at /component/1/ticket/create/
Exception Value: __init__() got an unexpected keyword argument
'jpic_field_options'
Please don't mind the possible problems of my 'formfield_callback'
argument, i'll fix that ...
I asked on IRC and failed to fix it. Any tip will be appreciated, note
that my understanding of metaclasses is currently limited so that's
why i tryed to "just copy and hack".
There might be a better way.
Regards, James.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---