2009-12-06 12 views
36

He creado una buena forma, y ​​una gran y complicada función 'agregar' para manejarla. Se inicia así ...¿Django edita el formulario basado en agregar formulario?

def add(req): 
    if req.method == 'POST': 
     form = ArticleForm(req.POST) 
     if form.is_valid(): 
      article = form.save(commit=False) 
      article.author = req.user 
      # more processing ... 

Ahora realmente no quieren duplicar toda esa funcionalidad en el método edit(), por lo que pensé edit podría utilizar la misma plantilla exacta, y tal vez sólo tiene que añadir un campo a id el formulario para que la función add supiera lo que estaba editando. Pero hay un par de problemas con este

  1. Dónde podría establecer article.id en el add func? Tendría que ser después de form.save porque es donde se crea el artículo, pero nunca llegaría a eso, porque el formulario no es válido debido a restricciones únicas (a menos que el usuario lo haya editado todo). Simplemente puedo eliminar la verificación is_valid, pero luego falla el form.save.
  2. Si el formulario realmente es no válido, el campo I añadido dinámicamente en la función de edición no se conserva.

Entonces, ¿cómo me ocupo de esto?

Respuesta

88

Si está ampliando su formulario de una ModelForm, utilice el argumento instance palabra clave. Aquí pasamos un instance existente o uno nuevo, dependiendo de si estamos editando o agregando un artículo existente. En ambos casos, el campo author se establece en la instancia, por lo que commit=False no es necesario. Tenga en cuenta también que supongo que solo el autor puede editar sus propios artículos, de ahí la respuesta HttpResponseForbidden.

from django.http import HttpResponseForbidden 
from django.shortcuts import get_object_or_404, redirect, render, reverse 


@login_required 
def edit(request, id=None, template_name='article_edit_template.html'): 
    if id: 
     article = get_object_or_404(Article, pk=id) 
     if article.author != request.user: 
      return HttpResponseForbidden() 
    else: 
     article = Article(author=request.user) 

    form = ArticleForm(request.POST or None, instance=article) 
    if request.POST and form.is_valid(): 
     form.save() 

     # Save was successful, so redirect to another page 
     redirect_url = reverse(article_save_success) 
     return redirect(redirect_url) 

    return render(request, template_name, { 
     'form': form 
    }) 

Y en su urls.py:

(r'^article/new/$', views.edit, {}, 'article_new'), 
(r'^article/edit/(?P<id>\d+)/$', views.edit, {}, 'article_edit'), 

La misma edit vista se utiliza tanto para adiciones y modificaciones, pero sólo la edición de patrones URL pasa un id a la vista. Para que esto funcione bien con su formulario que necesita para omitir el campo author de la forma:

class ArticleForm(forms.ModelForm): 
    class Meta: 
     model = Article 
     exclude = ('author',) 
+0

sí, es un 'ModelForm'. Necesitaba 'commit = False' por otros motivos. Un artículo está compuesto por un montón de cosas (incluidas algunas relaciones m2m). No * creo * que quería trabajar con 'instancia'. Aunque probaré esto. – mpen

+1

En ese caso, sugeriría poner las relaciones de m2m (et al) guardar/validar en el formulario en lugar de la vista ... anular el método guardar o posiblemente, buscar en conjuntos de formularios. Supongo que depende del contexto de con qué estás trabajando ... –

+5

¡Ejemplo genial y minucioso! ¡Gracias! Aprendí más que la solución a esta pregunta. – hobbes3

1

Puede tener el campo ID oculto en el formulario y para editarlo se lo pasará con el formulario para agregarlo, puede configurarlo en req.POST, p. Ej.

formData = req.POST.copy() 
formData['id'] = getNewID() 

y pasar esa FormData para formar

Cuestiones relacionadas