简体   繁体   中英

Deletion by tab button doesn't work

Several DEVICE forms can be displayed on a page (Order), as tabs. When a user closes a tab and hits save , then renters that particular Order (ID), the user still sees his deleted tab. As a quick workaround, a checkbox was built into the html code but this is not desired.

Currently the code in my view.py looks like this.

def edit_order(request,id = None, order_id = None):
    order = Order.objects.get(id=id)
    '''some stuff'''
    if request.method == 'POST': 
            formCustomer = CustomerModelForm(request.POST,instance=Customer.objects.get(order=order.id))
            formInfo = InfoModelForm(request.POST,instance=Info.objects.get(order=order.id))
            DBFormSet = modelformset_factory(DB, extra=1, can_delete=True, form=LUNModelForm)
            formset = DBFormSet(request.POST or None, queryset=DB)  
            if formset.is_valid():
                            for i,frm in enumerate(formset.forms):
            if frm.cleaned_data['id']: 
                if frm.is_valid():
                    if not frm.cleaned_data['capacityGB'] > 0:
                        frm.cleaned_data['id'].delete()
                    elif frm.cleaned_data['DELETE'] == True: 
                        frm.cleaned_data['id'].delete()
                        #frm.save() or formset.save() ??
                    else:
                        dev = frm.cleaned_data['id']
                        dev.capacity = frm.cleaned_data['capacity']
                        dev.save()

I suspected the matter that the tab was not remaining closed was an issue with " can_delete ", but it doesn't seem to make a difference when I added this. Then I read that the issue could be related to the formset.save , which also didn't resolve anything. Below the html code:

html:

                <ul class="nav nav-tabs" id="tab4Headers">

{% for form in formsetDEVICE.forms %}
  {% if forloop.first %}
    {% if form.errors %}
                <li class="active"><a href="#tab4_{{forloop.counter}}" data-toggle="tab">DEVICE <i class="icon-warning-sign"></i> </a></li> <!-- section 4.1 -->
    {% else %}
                <li class="active"><a href="#tab4_{{forloop.counter}}" data-toggle="tab">DEVICE</a></li> <!-- section 4.1 -->
    {% endif %}

  {% else %}
    {% if form.errors %}
                <li><a href="#tab4_{{forloop.counter}}" data-toggle="tab"><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE <i class="icon-warning-sign"></i> </a></i></li> <!-- section 4.2 ... 4.n -->
                <!--{% if formsetDEVICE.can_delete %}
                  <li>{{ form.DELETE }}</li>
                {% endif %}-->
    {% else %}
                <li><a href="#tab4_{{forloop.counter}}" data-toggle="tab"><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE</a></li> <!-- section 4.2 ... 4.n -->
                <!--{% if formsetDEVICE.can_delete %}
                  <li>{{ form.DELETE }}</li>
                {% endif %}-->
    {% endif %}
  {% endif %}
{% endfor %}
                </ul>

Since it is not clear how to delete the tab via closing the tab (and then hit the save button), the current work around is simply to insert a section on the tab with a checkbox included, as so:

  {# --- delete item --- #}
  {% if form.instance.pk %}
  {# render row for DELETE-flag only for forms with existing instance #}
  <tr>
  <td colspan="2">
  </td>
  <td colspan="2">
    edit Action required: <br/><br/>
    {{form.DELETE|safe}} delete this DEVICE from the Order.
  </td>
  </tr>
  {% endif %}
  {# --- END delete item --- #}

The current workaround works, but this is not the desired functionality. I've tried some of the suggestions as seen here , but to no avail. I think the problem is more related to the link between the html and the view.py (so something to do with frm.cleaned_data['DELETE'] though I could be wrong.

EDIT:

I suspect to get around this, js code and/or css needs to be inserted.

I was having the same problem with inlineformset_factory . Reading the base Django classes, i found the problem seems to be in BaseFormSet class (or some like that), the _should_delete_form() method looks for the forms DELETE value in cleaned_data, but using debugging i found that the DELETE value doesn't exist in cleaned_data, neither the DELETE field exists by the time cleaned_data is populated.

I think this could be because the DELETE field is dynamically created by FormSet Classes, but cleaned_data is populated by the Form class before the DELETE field is created (somewhere on forms init? maybe) so as this field doesn't exists, cleaned_data DELETE value isn't populated.

Somewhere in the base FormSet classes, the dynamically created DELETE field value have to be included in cleaned_data, BUT i found a quick and temporary solution to this, Add the DELETE field to the form class:

class RutinaForm(ModelForm):
    DELETE = forms.BooleanField(required=False, widget=forms.CheckboxInput())

    class Meta:
        model = Rutina
        fields = '__all__'
        exclude = ('usuario',)
        widgets = { .........}

This way the DELETE field exists so its value gets cleaned and added to cleaned_data.
This can be seen like a "machetazo", but it works! at least temporary. I will continue reading the base code and look if it is a bug, or what is happening.

Note: Sorry for my english, and i'm not an expert so PLEASE give me your comments.

This is my view if you need it, or if you can find what is wrong:

rutinaFormSet = inlineformset_factory(Usuario, Rutina, form=RutinaForm, can_delete=True, extra=1)
if request.method == 'POST':
    formSet = rutinaFormSet(request.POST, instance=usuario)
    if formSet.is_valid():

        formSet.save()

else:
    formSet = rutinaFormSet(instance=usuario)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM