Login

Handles Inline Formsets and also "in-standard-way" normal forms

Author:
sebnapi
Posted:
February 27, 2012
Language:
Python
Version:
1.4
Tags:
forms formset inline inlineformset inline_formset
Score:
1 (after 1 ratings)

If you read the docstring and the example you should get a clue what this Code does. I didn't want a big function everytime that handles every specific form, formset combinations so this how i can add/edit Models with specific Forms given to the magic_handle_inlineformsets function. It also works for Forms without innline_formsets.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def magic_handle_form(Class, Class_form, request, instance=None):
    return magic_handle_inlineformsets(Class, Class_form, request, {}, instance)

def magic_handle_inlineformsets(Class, Class_form, request, inline_formset_dict, instance=None):
    """ give me a main Class (Recipe), ClassForm (RecipeForm) and maybe Instance (recipe),
        the request and a inline_formset_dict like:
        {
            "recipe_ingredients":IngredientsRecipeFormSet,
            "recipe_inline2": Inline2RecipeFormSet
        }
        and you get back a formset_dict you can iterate through in template, "_formset" will be appended to keys
        or a success with a dict of the saved model instances, "obj" will be key for main model
    """
    formset_dict = {}
    dont_save = False
    got_post = request.method == 'POST'
    result = {}
    if got_post:
        class_form = Class_form(request.POST, instance=instance) if instance else Class_form(request.POST)
        if class_form.is_valid():
            obj = class_form.save(commit=False)
            for key,form in inline_formset_dict.items():
                formset_dict[key+"_formset"] = form(request.POST, request.FILES, instance=obj)
                if not formset_dict[key+"_formset"].is_valid():
                    dont_save = True
            if dont_save:
                result = {"form":class_form}
                result.update(formset_dict)
                return result
            else:
                obj.save()
                class_form.save_m2m()
                new_objs_dict = {}
                for key,form in formset_dict.items():
                    new_objs_dict[key.rsplit("_formset",1)[0]] = form.save()
                    if hasattr(form, "save_m2m"):
                        form.save_m2m()
                result = {"obj":obj}
                result.update(new_objs_dict)
                return result
    if instance:
        obj = instance
    else:
        obj = Class()
    class_form = Class_form(request.POST, request.FILES, instance=obj) if got_post else Class_form(instance=obj)
    for key,form in inline_formset_dict.items():
        formset_dict[key+"_formset"] = form(request.POST, request.FILES, instance=obj) if got_post else form(instance=obj)
    result = {"form":class_form}
    result.update(formset_dict)
    return result



######################### EXAMPLE USE ########################## in views.py

def add_edit_recipe(request, recipe_id=None, template_name='recipe.html'):
    _recipe= None
    used_form = RecipeAddForm
    if recipe_id:    # we want to edit a recipe
        _recipe = get_obj_from_site_or_404(Recipe, pk=recipe_id)
        used_form = RecipeEditForm                               #we want an other form for editions
    
    inline_formsets = {"ingredient":IngredientRecipeFormSet, "image":ImageRecipeFormSet}
    result = magic_handle_inlineformsets(Recipe, used_form, request, inline_formsets, instance=_recipe)

    if result.has_key("obj") and isinstance(result["obj"], Recipe):
        # so the Recipe is now saved and we can continue somewhere else
        next = reverse('recipes')
        return HttpResponseRedirect(next)
    ctx =  {}
    #kick the forms into the context
    ctx.update(result)
    context = RequestContext(request, ctx)
    return render_to_response(template_name, context_instance=context)

More like this

  1. InlineFormset Template by petry 6 years, 9 months ago
  2. Making a django inline (model) formset really tabular by fnl 6 years, 4 months ago
  3. Arbitrary length formset by Rupe 5 years, 12 months ago
  4. Dynamically adding forms to a formset with jQuery by elo80ka 6 years, 5 months ago
  5. Form with Two InlineFormSets by maeck 6 years, 8 months ago

Comments

Please login first before commenting.