django inlineformset_factory删除错误

时间:2015-08-17 16:50:27

标签: django django-forms django-templates django-1.8

我的formset有一个奇怪的问题。 当我添加或更新现有模型时,所有工作都完美,但当我检查模板中的单选按钮删除并保存时我有这个错误----->>>>:
TypeError at /pro/edit/carted/ncavl189kabp97/hozegyc3f93ehb9ana/

'NoneType' object is not callable

Request Method: POST Request URL: http://localhost:8000/pro/edit/carted/ncavl189kabp97/hozegyc3f93ehb9ana/ Django Version: 1.8.3 Exception Type: TypeError Exception Value:

'NoneType' object is not callable

Exception Location: C:\Python34\lib\site-packages\django\forms\models.py in save_existing_objects, line 754 Python Executable: C:\Python34\python.exe Python Version: 3.4.3

这是我的view.py

def edit_carted(request, place_code, det_seq):
    template_name = 'mealandscoreappmanager/edit_carted.html'
    args = {}
    args.update(csrf(request))
    get_mealplace = get_place_by_code(place_code)
    # On recupère le carted correspondant au detseq (equivalent id)
    carted_by_seq = get_cartdetail_by_seq(det_seq, get_mealplace)

    class RequiredFormSet(BaseInlineFormSet):
            def __init__(self, *args, **kwargs):
                super(RequiredFormSet, self).__init__(*args, **kwargs)
                for form in self.forms:
                    form.empty_permitted = False
    meal_extra_form_set = inlineformset_factory(
        CarteDetails,
        MealExtra,
        form=MealExtraForm,
        can_delete=True,
        extra=1, )

    if request.method == 'POST':
        form = CardDetailForm(
            request.POST, user=request.user, instance=carted_by_seq)
        extra_form_set = meal_extra_form_set(
            request.POST, request.FILES, instance=carted_by_seq)
        if form.is_valid() and extra_form_set.is_valid():
            form.save()
            extra_form_set.save()
            messages.success(request, DEFAULTMSG)
            return HttpResponseRedirect(
                reverse(
                    'manage-core:core-list-cartdetail',
                    args=(get_mealplace.code, ),
                    current_app=request.resolver_match.namespace,
                )
            )
    else:
        if get_mealplace.partner.account_user.has_perm(
            'mealandscoreappmanager.pro_account_manage_{0}'.format(
                request.user.profile.mealplace.code)
        ) is False:
            raise PermissionDenied

        # On genere le dictionnaire de données
        carted_data = get_initial_cartd_data(carted_by_seq)

        # On génère un formulaire simple correspondant au data dict
        form = CardDetailForm(
            initial=carted_data,
            user=request.user,
        )
        extra_form_set = meal_extra_form_set(instance=carted_by_seq)
        args['item_id'] = det_seq
    args['formset'] = extra_form_set
    args['form'] = form
    args['partner'] = get_mealplace
    return render_to_response(
        template_name,
        args,
        context_instance=RequestContext(request)
    )

def edit_carted(request, place_code, det_seq): template_name = 'mealandscoreappmanager/edit_carted.html' args = {} args.update(csrf(request)) get_mealplace = get_place_by_code(place_code) # On recupère le carted correspondant au detseq (equivalent id) carted_by_seq = get_cartdetail_by_seq(det_seq, get_mealplace) class RequiredFormSet(BaseInlineFormSet): def __init__(self, *args, **kwargs): super(RequiredFormSet, self).__init__(*args, **kwargs) for form in self.forms: form.empty_permitted = False meal_extra_form_set = inlineformset_factory( CarteDetails, MealExtra, form=MealExtraForm, can_delete=True, extra=1, ) if request.method == 'POST': form = CardDetailForm( request.POST, user=request.user, instance=carted_by_seq) extra_form_set = meal_extra_form_set( request.POST, request.FILES, instance=carted_by_seq) if form.is_valid() and extra_form_set.is_valid(): form.save() extra_form_set.save() messages.success(request, DEFAULTMSG) return HttpResponseRedirect( reverse( 'manage-core:core-list-cartdetail', args=(get_mealplace.code, ), current_app=request.resolver_match.namespace, ) ) else: if get_mealplace.partner.account_user.has_perm( 'mealandscoreappmanager.pro_account_manage_{0}'.format( request.user.profile.mealplace.code) ) is False: raise PermissionDenied # On genere le dictionnaire de données carted_data = get_initial_cartd_data(carted_by_seq) # On génère un formulaire simple correspondant au data dict form = CardDetailForm( initial=carted_data, user=request.user, ) extra_form_set = meal_extra_form_set(instance=carted_by_seq) args['item_id'] = det_seq args['formset'] = extra_form_set args['form'] = form args['partner'] = get_mealplace return render_to_response( template_name, args, context_instance=RequestContext(request) )

这是我的formset.js代码

$(document).ready(function () {
    // Code adapted from http://djangosnippets.org/snippets/1389/  
    function updateElementIndex(el, prefix, ndx) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + ndx + '-';
        if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
        replacement));
        if (el.id) el.id = el.id.replace(id_regex, replacement);
        if (el.name) el.name = el.name.replace(id_regex, replacement);
    }

    function deleteForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        if (formCount > 1) {
            // Delete the item/form
            $(btn).parents('.item').remove();
            var forms = $('.item'); // Get all the forms  
            // Update the total number of forms (1 less than before)
            $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
            var i = 0;
            // Go through the forms and set their indices, names and IDs
            for (formCount = forms.length; i < formCount; i++) {
                $(forms.get(i)).children().children().each(function () {
                    if ($(this).attr('type') == 'text') updateElementIndex(this, prefix, i);
                });
            }
        } // End if
        else {
            alert("Il faut au moins un supplement");
        }
        return false;
    }

    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        // You can only submit a maximum of 10 todo items 
        if (formCount < 10) {
            // Clone a form (without event handlers) from the first form
            var row = $(".item:first").clone(false).get(0);
            // Insert it after the last form
            $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);

            // Remove the bits we don't want in the new row/form
            // e.g. error messages
            $(".errorlist", row).remove();
            $(row).children().removeClass("error");

            // Relabel or rename all the relevant bits
            $(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                $(this).val("");
            });

            // Add an event handler for the delete item/form link 
            $(row).find(".delete").click(function () {
                return deleteForm(this, prefix);
            });
            // Update the total form count
            $("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
        } // End if
        else {
            alert("Sorry, you can only enter a maximum of ten items.");
        }
        return false;
    }
    // Register the click event handlers
    $("#add").click(function () {
        return addForm(this, "mealextra_set");
    });

    $(".delete").click(function () {
        return deleteForm(this, "mealextra_set");
    });
});
那是我的模板 $(document).ready(function () { // Code adapted from http://djangosnippets.org/snippets/1389/ function updateElementIndex(el, prefix, ndx) { var id_regex = new RegExp('(' + prefix + '-\\d+-)'); var replacement = prefix + '-' + ndx + '-'; if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement)); if (el.id) el.id = el.id.replace(id_regex, replacement); if (el.name) el.name = el.name.replace(id_regex, replacement); } function deleteForm(btn, prefix) { var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val()); if (formCount > 1) { // Delete the item/form $(btn).parents('.item').remove(); var forms = $('.item'); // Get all the forms // Update the total number of forms (1 less than before) $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length); var i = 0; // Go through the forms and set their indices, names and IDs for (formCount = forms.length; i < formCount; i++) { $(forms.get(i)).children().children().each(function () { if ($(this).attr('type') == 'text') updateElementIndex(this, prefix, i); }); } } // End if else { alert("Il faut au moins un supplement"); } return false; } function addForm(btn, prefix) { var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val()); // You can only submit a maximum of 10 todo items if (formCount < 10) { // Clone a form (without event handlers) from the first form var row = $(".item:first").clone(false).get(0); // Insert it after the last form $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300); // Remove the bits we don't want in the new row/form // e.g. error messages $(".errorlist", row).remove(); $(row).children().removeClass("error"); // Relabel or rename all the relevant bits $(row).children().children().each(function () { updateElementIndex(this, prefix, formCount); $(this).val(""); }); // Add an event handler for the delete item/form link $(row).find(".delete").click(function () { return deleteForm(this, prefix); }); // Update the total form count $("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1); } // End if else { alert("Sorry, you can only enter a maximum of ten items."); } return false; } // Register the click event handlers $("#add").click(function () { return addForm(this, "mealextra_set"); }); $(".delete").click(function () { return deleteForm(this, "mealextra_set"); }); });

那是我的model.py部分:

<div class="row">
        <div class="col-md-12">
            <form role="form form-horizontal" method="POST" action="" class="form-horizontal" enctype="multipart/form-data">
                {% csrf_token %}
                <div class="form-group">
                    <div class="col-md-12">
                        <div class="panel panel-primary">
                            <div class="panel-heading">{% trans "Définir menu" %}</div>
                            <div class="panel-body">
                                {% bootstrap_form form %}
                            </div>
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-12">
                        <div class="mealands-mmeal-content">
                            <div class="mmeal-content-heading">{% trans "Accompagnement (ou supplements)" %} <span class="pull-right"><a href="#" id="add" class="btn btn-primary"><i class="fa fa-plus-circle"></i> {% trans "Ajouter supplément" %}</a></span></div>
                            <p class="help-block">
                            </p>
                            <div class="mmeal-content-body">
                                {{ formset.management_form }}
                                <div class="row">
                                    {% for forms in formset %}
                                        {{forms.id}}
                                        <div class="col-md-4 item">
                                            <div lass="form-group">
                                                <label class="control-label" for="{{forms.name.id_for_label}}">
                                                    {{forms.name.label}}
                                                    {% if forms.name.field.required %}
                                                        <span class="special_class">*</span>
                                                    {% endif %}
                                                </label>
                                                {{forms.name}}
                                                <div class="input-error-container">
                                                {{ forms.name.errors }}
                                              </div>
                                            </div>
                                            <div lass="form-group">
                                                <label class="control-label" for="{{forms.taxe.id_for_label}}">
                                                    {{forms.taxe.label}}
                                                    {% if forms.taxe.field.required %}
                                                        <span class="special_class">*</span>
                                                    {% endif %}
                                                </label>
                                                {{forms.taxe}}
                                                <div class="input-error-container">
                                                {{ forms.taxe.errors }}
                                              </div>
                                            </div>
                                            <div lass="form-group">
                                                <label class="control-label" for="{{forms.dispo.id_for_label}}">
                                                    {{forms.dispo}}
                                                    {% trans "Disponible ?" %}
                                                    {% if forms.dispo.field.required %}
                                                        <span class="special_class">*</span>
                                                    {% endif %}
                                                </label>
                                            </div>
                                            {% if formset.can_delete %}
                                    {{forms.id}}
                                            <div lass="form-group">
                                                <label class="control-label" for="{{forms.DELETE.id_for_label}}">
                                                    {{forms.DELETE}}
                                                    {{forms.DELETE.label}}
                                                    {% if forms.DELETE.field.required %}
                                                        <span class="special_class">*</span>
                                                    {% endif %}
                                                </label>
                                            </div>
                                            {% endif %}
                                            <a href="#" class="delete btn btn-danger"><i class="fa fa-times-circle"></i> {% trans "Supprimer supplément" %}</a>
                                        </div>
                                    {% endfor %}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                {% buttons %}
                <button type="submit" class="btn btn-default" name="save_and_add_another">
                    <i class="fa fa-retweet"></i> {% trans "Enregistrer et ajouter nouveau" %}
                </button>
                <button type="submit" class="btn btn-primary" name="save">
                    <i class="fa fa-check-square-o"></i> {% trans "Enregistrer" %} 
                </button>
                {% if item_id %}
                    <a href="{% url "manage-core:core-delete-cartdetail" partner.code item_id %}" class="btn btn-danger"><i class="fa fa-times-circle"></i> {% trans "Supprimer" %}</a>
                {% endif %}
            {% endbuttons %}
            </form>
        </div>
</div>

<div class="row"> <div class="col-md-12"> <form role="form form-horizontal" method="POST" action="" class="form-horizontal" enctype="multipart/form-data"> {% csrf_token %} <div class="form-group"> <div class="col-md-12"> <div class="panel panel-primary"> <div class="panel-heading">{% trans "Définir menu" %}</div> <div class="panel-body"> {% bootstrap_form form %} </div> </div> </div> </div> <div class="form-group"> <div class="col-md-12"> <div class="mealands-mmeal-content"> <div class="mmeal-content-heading">{% trans "Accompagnement (ou supplements)" %} <span class="pull-right"><a href="#" id="add" class="btn btn-primary"><i class="fa fa-plus-circle"></i> {% trans "Ajouter supplément" %}</a></span></div> <p class="help-block"> </p> <div class="mmeal-content-body"> {{ formset.management_form }} <div class="row"> {% for forms in formset %} {{forms.id}} <div class="col-md-4 item"> <div lass="form-group"> <label class="control-label" for="{{forms.name.id_for_label}}"> {{forms.name.label}} {% if forms.name.field.required %} <span class="special_class">*</span> {% endif %} </label> {{forms.name}} <div class="input-error-container"> {{ forms.name.errors }} </div> </div> <div lass="form-group"> <label class="control-label" for="{{forms.taxe.id_for_label}}"> {{forms.taxe.label}} {% if forms.taxe.field.required %} <span class="special_class">*</span> {% endif %} </label> {{forms.taxe}} <div class="input-error-container"> {{ forms.taxe.errors }} </div> </div> <div lass="form-group"> <label class="control-label" for="{{forms.dispo.id_for_label}}"> {{forms.dispo}} {% trans "Disponible ?" %} {% if forms.dispo.field.required %} <span class="special_class">*</span> {% endif %} </label> </div> {% if formset.can_delete %} {{forms.id}} <div lass="form-group"> <label class="control-label" for="{{forms.DELETE.id_for_label}}"> {{forms.DELETE}} {{forms.DELETE.label}} {% if forms.DELETE.field.required %} <span class="special_class">*</span> {% endif %} </label> </div> {% endif %} <a href="#" class="delete btn btn-danger"><i class="fa fa-times-circle"></i> {% trans "Supprimer supplément" %}</a> </div> {% endfor %} </div> </div> </div> </div> </div> {% buttons %} <button type="submit" class="btn btn-default" name="save_and_add_another"> <i class="fa fa-retweet"></i> {% trans "Enregistrer et ajouter nouveau" %} </button> <button type="submit" class="btn btn-primary" name="save"> <i class="fa fa-check-square-o"></i> {% trans "Enregistrer" %} </button> {% if item_id %} <a href="{% url "manage-core:core-delete-cartdetail" partner.code item_id %}" class="btn btn-danger"><i class="fa fa-times-circle"></i> {% trans "Supprimer" %}</a> {% endif %} {% endbuttons %} </form> </div> </div>

现在,当我编辑现有的模型时,这一切都有效! 但当我检查删除({{form.delete}})时,我收到错误:&#39; NoneType&#39;对象不可调用 我检查了我的错误页面并看到了这条消息!

class CarteDetails(models.Model):
    PERIOD_DAY = (
        (MORNING, _('Matin')),
        (NOON, _('Midi')),
        (AFTERNOON, _('Après midi')),
        (EVENING, _('Soir')),
    )
    **Note that sequence is my primary key**
    sequence = models.CharField(max_length=25, primary_key=True)
    jour = models.CharField(
        _('Jour'), max_length=1, choices=DAYSLIST)
    period = models.CharField(
        _('Période de la journée'),
        max_length=1, choices=PERIOD_DAY, default=MORNING)
    date_add = models.DateTimeField(auto_now_add=True)
    meal = models.ForeignKey(
        Meal, verbose_name=_('Plat'), null=True)
    # We add s because in view we'll use formset
    format = models.ForeignKey(Format, verbose_name=_('Format'), null=True)
    price = models.DecimalField(
        _('Prix'),
        max_digits=8,
        decimal_places=2,
        db_index=True,
        null=True,
    )
    dispo = models.BooleanField(default=True)
    existed = models.BooleanField(default=True)

    def __str__(self):
        return '%s - %s - %s' % (
            self.get_jour_display(),
            self.mealformat, self.get_period_display())

    class Meta:
        ordering = ['sequence']


class MealExtra(models.Model):
    name = models.CharField(max_length=30)
    taxe = models.DecimalField(
        _('Taxe'),
        max_digits=8,
        decimal_places=2,
        db_index=True,
    )
    carted = models.ForeignKey(CarteDetails, null=True)
    formule = models.ForeignKey(MealFormat, null=True)
    dispo = models.BooleanField(default=True)
    existed = models.BooleanField(default=True)

class CarteDetails(models.Model): PERIOD_DAY = ( (MORNING, _('Matin')), (NOON, _('Midi')), (AFTERNOON, _('Après midi')), (EVENING, _('Soir')), ) **Note that sequence is my primary key** sequence = models.CharField(max_length=25, primary_key=True) jour = models.CharField( _('Jour'), max_length=1, choices=DAYSLIST) period = models.CharField( _('Période de la journée'), max_length=1, choices=PERIOD_DAY, default=MORNING) date_add = models.DateTimeField(auto_now_add=True) meal = models.ForeignKey( Meal, verbose_name=_('Plat'), null=True) # We add s because in view we'll use formset format = models.ForeignKey(Format, verbose_name=_('Format'), null=True) price = models.DecimalField( _('Prix'), max_digits=8, decimal_places=2, db_index=True, null=True, ) dispo = models.BooleanField(default=True) existed = models.BooleanField(default=True) def __str__(self): return '%s - %s - %s' % ( self.get_jour_display(), self.mealformat, self.get_period_display()) class Meta: ordering = ['sequence'] class MealExtra(models.Model): name = models.CharField(max_length=30) taxe = models.DecimalField( _('Taxe'), max_digits=8, decimal_places=2, db_index=True, ) carted = models.ForeignKey(CarteDetails, null=True) formule = models.ForeignKey(MealFormat, null=True) dispo = models.BooleanField(default=True) existed = models.BooleanField(default=True) 请我帮忙! 谢谢rakwen

0 个答案:

没有答案