Created
April 26, 2015 19:27
-
-
Save seanmavley/560442db0dd195185b86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) | |
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() | |
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): | |
""" | |
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)) | |
<!-- Template --> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Multiformset Demo</title> | |
<script src="{{ STATIC_URL }}js/jquery.min.js"></script> | |
<script src="{{ STATIC_URL }}js/jquery.formset.js"></script> | |
<script type="text/javascript"> | |
$(function() { | |
$(".inline.{{ ingredient_form.prefix }}").formset({ | |
prefix: "{{ ingredient_form.prefix }}", | |
}) | |
$(".inline.{{ instruction_form.prefix }}").formset({ | |
prefix: "{{ instruction_form.prefix }}", | |
}) | |
}) | |
</script> | |
</head> | |
<body> | |
<div> | |
<h1>Add Recipe</h1> | |
<form action="." method="post"> | |
{% csrf_token %} | |
<div> | |
{{ form.as_p }} | |
</div> | |
<fieldset> | |
<legend>Recipe Ingredient</legend> | |
{{ ingredient_form.management_form }} | |
{{ ingredient_form.non_form_errors }} | |
{% for form in ingredient_form %} | |
{{ form.id }} | |
<div class="inline {{ ingredient_form.prefix }}"> | |
{{ form.description.errors }} | |
{{ form.description.label_tag }} | |
{{ form.description }} | |
</div> | |
{% endfor %} | |
</fieldset> | |
<fieldset> | |
<legend>Recipe instruction</legend> | |
{{ instruction_form.management_form }} | |
{{ instruction_form.non_form_errors }} | |
{% for form in instruction_form %} | |
{{ form.id }} | |
<div class="inline {{ instruction_form.prefix }}"> | |
{{ form.number.errors }} | |
{{ form.number.label_tag }} | |
{{ form.number }} | |
{{ form.description.errors }} | |
{{ form.description.label_tag }} | |
{{ form.description }} | |
</div> | |
{% endfor %} | |
</fieldset> | |
<input type="submit" value="Add recipe" class="submit" /> | |
</form> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment