'''
Permite construir un formulario con los campos que se le especifiquen dado un `modelo`.
La relación del campo con el modelo puede ser tan larga como se desee, mientras se siga el formato
campo__campo.
Cuando los atributos son relaciones se puede especificar la relación o tomar atributos de la relación así:
* modelo__modelo_relacionado
Si se quieren atributos de la clase relacionada se puede solicitar nombrandolos:
* modelo__modelo_relacionado__atributo
.. note::
Cuidado con el guardado de este formulario, ya que no se puede garantizar que todos los campos requeridos
para construir los modelos están dentro del formulario, es decir, **NO** haga esto:
.. code:: python
form = MultiModeloForm(Modelo, [campo1, campo2])
formi = form.get_formulario()
formi.save()
'''
modelo = None
campos_modelos=None
campo_buscado=None
formulario=None
#FIXME inventarse una cache
def get_model_form(self, Model, Fields):
class ModelForm(forms.ModelForm):
class Meta:
model = Model
fields = Fields
return ModelForm
def buscar_campo(self, clase, campo):
if not '__' in campo:
fields = []
fields += clase._meta.fields
if hasattr(clase._meta, 'many_to_many') :
fields += clase._meta.many_to_many
for field in fields:
if campo == field.name:
if not clase.__name__ in self.campos_modelos:
self.campos_modelos[clase.__name__] = [clase]
self.campos_modelos[clase.__name__].append((field.name, self.campo_buscado))
return field
raise AttributeError
else:
campo_sp = campo.split('__')
campos = get_campos_por_clase(clase)
if campo_sp[0] in campos:
claser = campos[campo_sp[0]].related.parent_model
return self.buscar_campo( claser, '__'.join(campo_sp[1:]))
else:
raise AttributeError
def __init__(self, clase_base, campos):
'''
Esta clase es una constructora de formularios, no es el formulario.
para obtener el formulario debe hacer form.get_formulario()
'''
base = clase_base.__name__
self.campos_modelos = {}
self.modelo=clase_base
for x in campos:
self.campo_buscado = x
self.buscar_campo(clase_base, x)
formularios = {}
base_modelo = None
base_campos = None
for nombre, valores in self.campos_modelos.items():
modelo = valores[0]
fields = []
nombres_campos = SortedDict(valores[1:])
for x,y in nombres_campos.items():
fields.append(x)
if nombre == base:
base_modelo = modelo
base_campos = fields
else:
form = self.get_model_form(modelo, fields)()
# FIXME revisar para que sirve formularios[nombre]
#formularios[nombre] =[]
for nombre_f, valor in zip(form.fields.keys(), form.fields.values()):
if nombre_f in nombres_campos:
formularios[nombres_campos[nombre_f]] = valor
if not base_modelo:
base_modelo = clase_base
base_campos = []
class Multi_Model_Form(forms.ModelForm):
for nombre, valor in formularios.items() + [(None, None)]:
if nombre:
exec "%s = valor" % (nombre)
else:
exec "pass"
class Meta:
model=base_modelo
fields = base_campos
self.formulario = Multi_Model_Form
def get_formulario(self):
'''
Retorma el formulario creado
'''
return self.formulario
def get_modelo(self):
'''
Permite saber el modelo base del formulario
'''
return self.modelo
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-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAG%2B5VyOoHVuOH8EQa5HdfWfgqed%2BoaBoBHmnTov45VVZACi%3D2Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment