2016-11-08 6 views
-1

Я использовал этот отличный пост http://kevindias.com/writing/django-class-based-views-multiple-inline-formsets/ для настройки моего сайта. Мне было интересно, как автоматически сохранить поле пользователя в встроенный набор форм в представлениях (я использовал blockquote для изменений в оригинале). RecipeForm (смотри также ниже для контекста)Как сохранить встроенное пользовательское поле формы в Django, используя представления

self.object = form.save(commit=False) 
self.object.owner = self.request.user 
self.object.save() 

сохраняет красиво автоматически, но не

ingredient_form.owner= self.request.user 

Я знаю, Django предлагает использовать BaseInlineFormSet, но большинство людей предполагают сохранение поля пользователя в views.py и не форм или моделей по многим причинам. Буду признателен за любые предложения или ответы. Вот полный код:

models.py

from django.db import models 


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


class Ingredient(models.Model): 
    owner = models.ForeignKey(User) 
    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) 
    InstructionFormSet = inlineformset_factory(Recipe, Instruction) 

views.py

from django.http import HttpResponseRedirect 
from django.views.generic import CreateView 
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 = 'success/' 

    def get(self, request, *args, **kwargs): 
     """ 
     Handles GET requests and instantiates blank versions of the form 
     and its inline formsets. 
     """ 
     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): 
     """ 
     Handles POST requests, instantiating a form instance and its inline 
     formsets with the passed POST variables and then checking them for 
     validity. 
     """ 
     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): 
     """ 
     Called if all forms are valid. Creates a Recipe instance along with 
     associated Ingredients and Instructions and then redirects to a 
     success page. 
     """ 
     self.object = form.save(commit=False) 
     self.object.owner = self.request.user 
     self.object.save() 
     ingredient_form.instance = self.object 
     ingredient_form.owner= self.request.user 
     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): 
     """ 
     Called if a form is invalid. Re-renders the context data with the 
     data-filled forms and errors. 
     """ 
     return self.render_to_response(
      self.get_context_data(form=form, 
            ingredient_form=ingredient_form, 
            instruction_form=instruction_form)) 

ответ

0

Я еще некоторое исследование и решение выглядит довольно сложным следуя этому руководству о том, как добавить custom formset saving, но изменен для BaseInlineFormset как упоминание выше. Я понял, что будет проще просто сделать ModelForms для каждой модели, а затем связать их в представлении, так как мне нужна только одна дочерняя форма за один раз в добавлении нового представления рецепта и может повторно использовать код ModelForm.

вот новый код, который отлично работает! Не стесняйтесь обращаться, если вам нужна дополнительная информация.

forms.py

from django.forms import ModelForm 
from .models import Recipe, Ingredient, Instruction 


class RecipeForm(ModelForm): 

    class Meta: 
     model = Recipe 
     exclude = ['owner',] 

class IngredientForm(ModelForm): 

    class Meta: 
     model = Ingredient 
     exclude = ['owner','recipe',] 

class InstructionForm(ModelForm): 

    class Meta: 
     model = Instruction 
     exclude = ['recipe',] 

views.py

from .forms import IngredientForm, InstructionForm, RecipeForm 


def add_new_value(request): 
    rform = RecipeForm(request.POST or None) 
    iform = IngredientForm(request.POST or None) 
    cform = InstructionForm(request.POST or None) 
    if rform.is_valid() and iform.is_valid() and cform.is_valid(): 
     rinstance = rform.save(commit=False) 
     iinstance = iform.save(commit=False) 
     cinstance = cform.save(commit=False) 
     user = request.user 
     rinstance.owner = user 
     rinstance.save() 
     iinstance.owner = user 
     cinstance.owner = user 
     iinstance.recipe_id = rinstance.id 
     cinstance.recipe_id = rinstance.id 
     iinstance.save() 
     cinstance.save() 
     return HttpResponseRedirect('/admin/') 
    context = { 
     'rform' : rform, 
     'iform' : iform, 
     'cform' : cform, 
    } 
    return render(request, "add_new_recipe.html", context) 

шаблона: add_new_recipe.html

<!DOCTYPE html> 
<html> 
<head> 
    <title>Add Recipe</title> 
</head> 

<body> 
    <div> 
     <h1>Add Recipe</h1> 
     <form action="" method="post"> 
      {% csrf_token %} 
      <div> 
       {{ rform.as_p }} 
       {{ iform.as_p }} 
       {{ cform.as_p }} 
      </div> 
      <input type="submit" value="Add recipe" class="submit" /> 
     </form> 
    </div> 
</body> 
</html> 

 Смежные вопросы

  • Нет связанных вопросов^_^