2015-01-10 58 views
14

我一直在努力做的Django的基於類的CreateView的和更新視圖與多個在線表單集Django的基於類的CreateView的和更新視圖與多個在線表單集

CreateView的工作正常,但更新視圖不​​能正常工作,如果沒有人嘗試過的UpdateView與多個內聯formset,任何人都試圖分享updateview代碼片段。

# models.py 
from django.db import models 

class Recipe(models.Model): 
    title = models.CharField(max_length=255) 
    description = models.TextField() 

class Ingredient(models.Model): 
    recipe = models.ForeignKey(Recipe) 
    description = models.CharField(max_length=255) 

class Instruction(models.Model): 
    recipe = models.ForeignKey(Recipe) 
    number = models.PositiveSmallIntegerField() 
    description = models.TextField() 


# forms.py 
from django.forms import ModelForm 
from django.forms.models import inlineformset_factory 
from .models import Recipe, Ingredient, Instruction 

class RecipeForm(ModelForm): 
    class Meta: 
     model = Recipe 

IngredientFormSet = inlineformset_factory(Recipe, Ingredient, extra=0) 
InstructionFormSet = inlineformset_factory(Recipe, Instruction, extra=0) 


# views.py 
from django.http import HttpResponseRedirect 
from django.views.generic.edit import CreateView, UpdateView 
from django.shortcuts import get_object_or_404 

from .forms import IngredientFormSet, InstructionFormSet, RecipeForm 
from .models import Recipe 

class RecipeCreateView(CreateView): 
    template_name = 'recipe_add.html' 
    model = Recipe 
    form_class = RecipeForm 
    success_url = '/account/dashboard/' 

    def get(self, request, *args, **kwargs): 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     ingredient_form = IngredientFormSet() 
     instruction_form = InstructionFormSet() 
     return self.render_to_response(
      self.get_context_data(form=form, 
            ingredient_form=ingredient_form, 
            instruction_form=instruction_form)) 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     ingredient_form = IngredientFormSet(self.request.POST) 
     instruction_form = InstructionFormSet(self.request.POST) 
     if (form.is_valid() and ingredient_form.is_valid() and 
      instruction_form.is_valid()): 
      return self.form_valid(form, ingredient_form, instruction_form) 
     else: 
      return self.form_invalid(form, ingredient_form, instruction_form) 

    def form_valid(self, form, ingredient_form, instruction_form): 
     self.object = form.save() 
     ingredient_form.instance = self.object 
     ingredient_form.save() 
     instruction_form.instance = self.object 
     instruction_form.save() 
     return HttpResponseRedirect(self.get_success_url()) 

    def form_invalid(self, form, ingredient_form, instruction_form): 
     return self.render_to_response(
      self.get_context_data(form=form, 
            ingredient_form=ingredient_form, 
            instruction_form=instruction_form)) 

class RecipeUpdateView(UpdateView): 
    template_name = 'recipe_add.html' 
    model = Recipe 
    form_class = RecipeForm 

    def get_success_url(self): 
     self.success_url = '/account/dashboard/' 
     return self.success_url 

    def get_context_data(self, **kwargs): 
     context = super(RecipeUpdateView, self).get_context_data(**kwargs) 
     if self.request.POST: 
      context['form'] = RecipeForm(self.request.POST, instance=self.object) 
      context['ingredient_form'] = IngredientFormSet(self.request.POST, instance=self.object) 
      context['instruction_form'] = InstructionFormSet(self.request.POST, instance=self.object) 
     else: 
      context['form'] = RecipeForm(instance=self.object) 
      context['ingredient_form'] = IngredientFormSet(instance=self.object) 
      context['instruction_form'] = InstructionFormSet(instance=self.object) 
     return context 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     ingredient_form = IngredientFormSet(self.request.POST) 
     instruction_form = InstructionFormSet(self.request.POST) 
     if (form.is_valid() and ingredient_form.is_valid() and 
      instruction_form.is_valid()): 
      return self.form_valid(form, ingredient_form, instruction_form) 
     else: 
      return self.form_invalid(form, ingredient_form, instruction_form) 

    def form_valid(self, form, ingredient_form, instruction_form): 
     self.object = form.save() 
     ingredient_form.instance = self.object 
     ingredient_form.save() 
     instruction_form.instance = self.object 
     instruction_form.save() 
     return HttpResponseRedirect(self.get_success_url()) 

    def form_invalid(self, form, ingredient_form, instruction_form): 
     return self.render_to_response(
      self.get_context_data(form=form, 
            ingredient_form=ingredient_form, 
            instruction_form=instruction_form)) 

在此先感謝。

+1

原帖[多聯表單集Django的基於類的意見(http://kevindias.com/writing/django-class-based-views-multiple-inline-formsets/ ) –

+0

@vishes_shell現在鏈接已經死了。 – datakid

回答

5

我的猜測是,你不能在UpdateView覆蓋post方法做

self.object = None 

。因此,嘗試

self.object = self.get_object() 

而是,一旦您在這種情況下已經有一個對象實例。

-1

所以我認識的模型形成這種post。若要更新視圖工作正常,你將不得不這樣做至少有兩個,也許三件事情:

  1. 更新self.object = self.get_object() - 在這之後,你的動態添加應該工作的能力。

  2. 要使動態刪除正確更新,您需要使用form.DELETE(兩處,成分和說明)更改模板。

    {{ form.description }} 
    {% if form.instance.pk %}{{ form.DELETE }}{% endif %} 
    
  3. 不確定是否有必要,但我也加了can_delete到工廠。

    IngredientFormSet = inlineformset_factory(Recipe, Ingredient, fields=('description',), extra=3, can_delete=True) 
    InstructionFormSet = inlineformset_factory(Recipe, Instruction, fields=('number', 'description',), extra=1, can_delete=True) 
    
+0

該評論中的鏈接已經失效。 – datakid

1

我不認爲的UpdateView的規則形式已被添加到上下文,因爲它的存在反正。使用inlineformsets的工作更新視圖可以實現得更簡單。我基於此此Question

class RecipeUpdateView(UpdateView): 
    model = Recipe 
    form_class = RecipeUpdateForm 
    success_url = "/foo/" 

    def get_success_url(self): 
     self.success_url = '/account/dashboard/' 
     return self.success_url 

    def get_object(self): 
     return #your object 

    def get_context_data(self, **kwargs): 
     context = super(ShoppingCartView, self).get_context_data(**kwargs) 
     if self.request.POST: 
      context['ingredient_form'] = IngredientFormSet(self.request.POST, instance=self.object) 
      context['instruction_form'] = InstructionFormSet(self.request.POST, instance=self.object) 
     else: 
      context['ingredient_form'] = IngredientFormSet(instance=self.object) 
      context['instruction_form'] = InstructionFormSet(instance=self.object) 
     return context 

    def form_valid(self, form): 
     context = self.get_context_data() 
     ingredient_form = context['ingredient_form'] 
     instruction_form = context['instruction_form'] 
     if ingredient_form.is_valid() and instruction_form.is_valid(): 
      self.object = form.save() 
      ingredient_form.instance = self.object 
      ingredient_form.save() 
      instruction_form.instance = self.object 
      instruction_form.save() 
     return self.render_to_response(self.get_context_data(form=form)) 
相關問題