you tag register form forget example dynamically did django

tag - formset django implementation



Pasando inicial en ModelFormSet de Django (10)

Creo que puedes usar el argumento inicial, como con los conjuntos de formularios regulares http://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset

Tengo un formset modelo al que necesito pasar la palabra clave inicial a (para tener algunos valores iniciales en el formset, como la fecha establecida hoy). Por lo que puedo decir, el argumento queryset (que por defecto es YourModel.objects.all ()) anula esta capacidad para la creación de formularios vacíos iniciales. Especifiqué el queryset como: YourModel.objects.none (), lo que impide que complete el formulario con las entradas de la base de datos, pero todavía no puedo averiguar cómo pasar el inicial de manera efectiva. ¿Necesito subclasificar un método de ModelForm?


Después de dos días encontré esto: http://streamhacker.com/2010/03/01/django-model-formsets/

def custom_field_callback(field): return field.formfield(required=False) FormSet = modelformset_factory(model, formfield_callback=custom_field_callback) def custom_field_callback(field): if field.name == ''optional'': return field.formfield(required=False) elif field.name == ''text'': return field.formfield(widget=Textarea) elif field.name == ''integer'': return IntegerField() else: return field.formfield()


En Django 1.4, la regla cambió: el número de iniciales a mostrar corresponde al parámetro "extra". https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

En mi caso, el recuento de los parámetros iniciales varía dinámicamente, por lo que encontré la siguiente forma:

initial=[{''name'': ''Some Name''},{''name'': ''Another Name''}] formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), initial=initial, extra=len(initial)) class MyBaseFormSet(BaseModelFormSet): def __init__(self, *args, **kwargs): self.extra = kwargs.pop(''extra'', self.extra) super(MyBaseFormSet, self).__init__(*args, **kwargs)

proporcionado, ExampleModelFormSet se basa en MyBaseFormSet


La forma sencilla de pasar datos iniciales con el mismo número de formularios adicionales:

MyModelFormSet = lambda *a, **kw: modelformset_factory(MyModel, extra=kw.pop(''extra'', 1))(*a, **kw)

Uso en vistas:

initial=[{''name'': ''Some Name''},{''name'': ''Another Name''} formset = MyModelFormSet(queryset=MyModel.objects.none(), initial, extra=len(initial))})


La mejor manera que he encontrado para hacer esto es simplemente ajustar manualmente el atributo "extra" del objeto formset después de la inicialización. Esto ha sido probado y funciona en Django 1.9.

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1) formset = ExampleModelFormSet(initial=[{''name'': ''Some Name''}, {''name'': ''Another Name''}]) formset.extra = 3

Esto escupirá 3 formularios (2 prepopulados y 1 en blanco).

Si quieres algo más dinámico (por ejemplo, initial es una var calculada en otro lugar), puedes hacer algo como esto:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1) formset = ExampleModelFormSet(initial=initial) formset.extra += len(initial)

Espero que ayude.



Puede alterar los datos iniciales después.

Por ejemplo:

# Construct the FormSet class ExampleFormSet = modelformset_factory(ParentModel, ChildModel) # Set the initial data initial_data = {''field1'': 1} for form in ExampleFormSet.extra_forms: for field in form.fields: field.initial = initial_data[field.name]


Todavía es posible pasar inicial a un ModelFormSet.

from django.forms.models import modelformset_factory from example.models import ExampleModel ExampleModelFormSet = modelformset_factory(ExampleModel) formset = ExampleModelFormSet(initial=[{''name'': ''Some Name''}, {''name'': ''Another Name''}])

Si esto no es lo que buscas, ¿puedes explicar más tu pregunta?

EDITAR:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2) formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), initial=[{''name'': ''Some Name''}, {''name'': ''Another Name''}])


Una solución simple podría ser que pase un formulario que extienda un modelform () a un formset (en lugar de modelformset).

De esa manera puede establecer valores iniciales en el formulario.


Usted está pasando un queryset vacío a ModelFormset.

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2) formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), initial=[{''name'': ''Some Name''}, {''name'': ''Another Name''}])

que es precisamente la manera de lograr lo que quieres. Tiene sentido pasar un conjunto de consultas vacío, de lo contrario los valores iniciales anularán el valor de la base de datos del modelo.

Y si supongo que está pasando un queryset no vacío, y aún así desea que sus formularios adicionales se llenen con valores iniciales, puede anular el Formset .

from django.forms.models import modelformset_factory ExampleFormset = modelformset_factory(OpenIDProfile, extra=3) class myFormset(ExampleFormset): def _construct_form(self, i, **kwargs): """ Instantiates and returns the i-th form instance in a formset. """ if self.is_bound and i < self.initial_form_count(): pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) pk = self.data[pk_key] pk_field = self.model._meta.pk pk = pk_field.get_db_prep_lookup(''exact'', pk) if isinstance(pk, list): pk = pk[0] kwargs[''instance''] = self._existing_object(pk) if i < self.initial_form_count() and not kwargs.get(''instance''): kwargs[''instance''] = self.get_queryset()[i] defaults = {''auto_id'': self.auto_id, ''prefix'': self.add_prefix(i)} if self.data or self.files: defaults[''data''] = self.data defaults[''files''] = self.files # Check to confirm we are not overwriting the database value. if not i in range(self.initial_form_count()) and self.initial: try: defaults[''initial''] = self.initial[i - self.initial_form_count()] except IndexError: pass # Allow extra forms to be empty. if i >= self.initial_form_count(): defaults[''empty_permitted''] = True defaults.update(kwargs) form = self.form(**defaults) self.add_fields(form, i) return form

Nota: initial es lista de dicts. Es deseable tener elementos en la lista exactamente igual al número de extra.