formtools form django django-forms django-views django-formwizard

formtools - ¿Forma la información inicial del asistente para que la edición no se cargue correctamente en Django?



form wizard django (1)

Tengo una lista de tres páginas que sale de un solo modelo. Pude guardar el modelo por primera vez, pero cuando quiero editar el modelo, solo el primer formulario muestra el valor inicial, los formularios posteriores no muestran los datos iniciales. pero cuando initial_dict el initial_dict desde las vistas, puedo ver todas las vistas iniciales correctamente. Seguí este blog en el asistente de formularios.

Aquí está mi model.py:

class Item(models.Model): user=models.ForeignKey(User) price=models.DecimalField(max_digits=8,decimal_places=2) image=models.ImageField(upload_to="assets/", blank=True) description=models.TextField(blank=True) def __unicode__(self): return ''%s-%s'' %(self.user.username, self.price)

urls.py:

urlpatterns = patterns('''', url(r''^create/$'', MyWizard.as_view([FirstForm, SecondForm, ThirdForm]), name=''wizards''), url(r''^edit/(?P<id>/d+)/$'', ''formwizard.views.edit_wizard'', name=''edit_wizard''), )

forms.py:

class FirstForm(forms.Form): id = forms.IntegerField(widget=forms.HiddenInput, required=False) price = forms.DecimalField(max_digits=8, decimal_places=2) #add all the fields that you want to include in the form class SecondForm(forms.Form): image = forms.ImageField(required=False) class ThirdForm(forms.Form): description = forms.CharField(widget=forms.Textarea)

views.py:

class MyWizard(SessionWizardView): template_name = "wizard_form.html" file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT)) #if you are uploading files you need to set FileSystemStorage def done(self, form_list, **kwargs): for form in form_list: print form.initial if not self.request.user.is_authenticated(): raise Http404 id = form_list[0].cleaned_data[''id''] try: item = Item.objects.get(pk=id) ###################### SAVING ITEM ####################### item.save() print item instance = item except: item = None instance = None if item and item.user != self.request.user: print "about to raise 404" raise Http404 if not item: instance = Item() for form in form_list: for field, value in form.cleaned_data.iteritems(): setattr(instance, field, value) instance.user = self.request.user instance.save() return render_to_response(''wizard-done.html'', { ''form_data'': [form.cleaned_data for form in form_list], }) def edit_wizard(request, id): #get the object item = get_object_or_404(Item, pk=id) #make sure the item belongs to the user if item.user != request.user: raise HttpResponseForbidden() else: #get the initial data to include in the form initial = {''0'': {''id'': item.id, ''price'': item.price, #make sure you list every field from your form definition here to include it later in the initial_dict }, ''1'': {''image'': item.image, }, ''2'': {''description'': item.description, }, } print initial form = MyWizard.as_view([FirstForm, SecondForm, ThirdForm], initial_dict=initial) return form(context=RequestContext(request), request=request)

modelo:

<html> <body> <h2>Contact Us</h2> <p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p> {% for field in form %} {{field.error}} {% endfor %} <form action={% url ''wizards'' %} method="post" enctype="multipart/form-data">{% csrf_token %} <table> {{ wizard.management_form }} {% if wizard.form.forms %} {{ wizard.form.management_form }} {% for form in wizard.form.forms %} {{ form }} {% endfor %} {% else %} {{ wizard.form }} {% endif %} </table> {% if wizard.steps.prev %} <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button> <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button> {% endif %} <input type="submit" value="Submit" /> </form> </body> </html>

EDITAR: uno que noté es el siguiente: en el modo de edición, es decir, cuando estoy en la siguiente url: http://127.0.0.1:8000/wizard/edit/1/ , muestra los primeros datos del formulario correctamente, y cuando hago clic en enviar, no me lleva al paso 2 del modo de edición, es decir, la URL cambia a http://127.0.0.1:8000/wizard/create/ .

Si al hacer submit en submit en edit url (como /wizard/edit/1 ) en el primer paso, se mantiene la misma URL, entonces el formulario obtendría sus datos iniciales en el siguiente paso. pero no puedo imaginar cómo evitar que la URL cambie a /wizard/create


El error parece trivial. En su plantilla, la acción del formulario tiene url de wizards , que es url de crear vista. Por lo tanto, cuando se envía el formulario va a /wizard/create .

Para poder usar la plantilla para ambas vistas, puede eliminar el atributo de action de la etiqueta del form . El formulario se enviará a la URL actual que se puede crear o editar.

Así que cambie su plantilla para tener una etiqueta de form como

<form method="post" enctype="multipart/form-data">

EDITAR: para guardar el artículo

Actualiza tu vista como:

def done(self, form_list, **kwargs): for form in form_list: print form.initial if not self.request.user.is_authenticated(): raise Http404 id = form_list[0].cleaned_data[''id''] try: item = Item.objects.get(pk=id) print item instance = item except: item = None instance = None if item and item.user != self.request.user: print "about to raise 404" raise Http404 if not item: instance = Item() #moved for out of if for form in form_list: for field, value in form.cleaned_data.iteritems(): setattr(instance, field, value) instance.user = self.request.user instance.save() return render_to_response(''wizard-done.html'', { ''form_data'': [form.cleaned_data for form in form_list], })