django-dynamic-formset creating two add/remove lin

2019-06-11 13:42发布

For some reason my implementation of django-dynamic-formset is acting a little funny.

It is creating two add/remove links for each dynamic formset in my template.

I have been fiddling around trying to figure this out for a bit and its gotten the best of me.

here is a screen shot of the error i am talking about

i can also provide a login if you would like to trigger the error on your own here is my template:

<head>
    <script type="text/javascript" src="{{ STATIC_URL }}jquery.formset.js"></script>
    <script type="text/javascript">
       $(function() {
           $('#ingredients tbody tr').formset({
               prefix: '{{ ingredients_formset.prefix }}',
               formCssClass: 'dynamic-ingredients'
           });
            $('#steps tbody tr').formset({
               prefix: '{{ steps_formset.prefix }}',
               formCssClass: 'dynamic-steps'
           });
       })
   </script>
</head>
<body>
<form action="{% url cookbook.views.createrecipe %}" method="POST" id="ingredients">
    {% csrf_token %}
<table>
    <tbody>
        <tr>
            <label>
                Ingredients:
            </label>
        </tr>

        <tr>
            <td>
                <input type="text" cols="40" rows="10" />
            </td>
        </tr>
    </tbody>
</table>
</form>
<form action="{% url cookbook.views.createrecipe %}" method="POST" id="steps">
    {% csrf_token %}
<table>
    <tbody>
        <label>
            Steps:
        </label>
        <tr>
            <td>
                <input type="text"  cols="40" rows="10" />
            </td>
        </tr>
    </tbody>
</table>
</form>
</body>

here is the forms.py

class RecipeForm(forms.ModelForm):
    reset_recipe = forms.CharField(widget=forms.HiddenInput(), required = False)
    class Meta:
        model = Recipe
        widgets = {'original_cookbook':forms.HiddenInput(),
                    'pub_date':forms.HiddenInput(),
                    'author':forms.HiddenInput()}

        fields =("name", "picture","ingredients","steps","prep_time","type",'reset_recipe')

class CookbookForm(forms.ModelForm):
    class Meta:
        model = Cookbook


class StepsForm(forms.Form):
    Step = forms.CharField()

StepsFormSet = formset_factory(RecipeForm, StepsForm, can_order=True, can_delete=True, extra = 0)

class IngredientsForm(forms.Form):
    Ingredient = forms.CharField()

IngredientsFormSet = formset_factory(RecipeForm, IngredientsForm, can_order=True, can_delete=True, extra = 0)

and the view:

def createrecipe(request):
    RecipeForm = RecipeForm(request.POST)
    IngredientsFormSet = formset_factory(IngredientsForm)
    StepsFormSet = formset_factory(StepsForm)
    if request.method == 'POST':
        form = RecipeForm(request.POST)
        ingredients_formset = IngredientsFormSet(request.POST, request.FILES, prefix='ifs')
        steps_formset = StepsFormSet(request.POST, request.FILES, prefix='sfs')
        if form.is_valid() and ingredients_formset.is_valid() and steps_formset.is_valid():
            print "form is valid"
            new_recipe = form.save(commit=False)
            new_recipe.original_cookbook = request.user.cookbooks.all()[0]
            new_recipe.author = request.user.cookbooks.all()[0].name
            new_recipe.steps = steps_formset
            new_recipe.ingredients = ingredients_formset
            new_recipe.save()
            cookbooks = request.user.cookbooks.all()
            cookbook = cookbooks[0]
            cookbook.recipes.add(new_recipe)
            form.save_m2m()             
            t = loader.get_template('cookbook/create_form.html')
            c = RequestContext(request, {
            'form': new_recipe,
            })

            data = {
            'replace': True,
            'form': t.render(c),
            'success': True,
            }

            json = simplejson.dumps(data)
            return HttpResponse(json, mimetype='text/plain')
        else:
            print "form is invalid"
            form = RecipeForm(request.POST)
            ingredients_formset = IngredientsFormSet(request.POST, request.FILES, prefix='ifs')
            steps_formset = StepsFormSet(request.POST, request.FILES, prefix='sfs')
            t = loader.get_template('cookbook/create_form.html')
            c = RequestContext(request, {
                'form':form,
            })

            data ={
                'form': t.render(c),
                'success': False,
            }

            json = simplejson.dumps(data)
            return HttpResponse(json, mimetype='text/plain')    

1条回答
放荡不羁爱自由
2楼-- · 2019-06-11 14:28

You can use the amazing django-dynamic-formset jQuery plugin by ELO80KA

I'm using it on a project right now, let me show you how I'm doing it right now, lets take a look of the markup:

<div id="id_p_i_c_formset_div">
{% for form in p_i_c_formset.forms %}
    <div class="p_i_c_child_formset row-fluid">
        {{ form.id }}
        <h2>year</h2>
        {{ form.year }}
        <h2>product_category</h2>
        {{ form.product_category }}
        <h2>insurance_company</h2>
        {{ form.insurance_company }}
        <h2>value</h2>
        {{ form.value|attr:"placeholder:insurance_claims" }}
        <h2>result</h2>
        {{ form.result }}
    </div>
{% endfor %}
{{ p_i_c_formset.management_form }}
</div>

Then, in the javascript you need to do the correct selector (where the fields of your formset lives), this is where the plugin will grab the code to clone it with the proper ids and names, don't forget to pase it the "prefix" of the formset:

$(function(){
    $('form#my-personal-info #id_p_i_c_formset_div .p_i_c_child_formset').formset({
        prefix: '{{ p_i_c_formset.prefix }}'
    });
});

The plugin will automatically create remove and add button.

查看更多
登录 后发表回答