nicorellius
nicorellius

Reputation: 4043

Django and AJAX: Delete Multiple Items wth Check Boxes

I have seen several posts that describe deleting items in Django with views and check boxes. I have accomplished deleting single items with AJAX. My current problem is that I cannot figure out how to delete multiple items with check boxes and AJAX in my Django application.

I originally used Django's GCBV, DeleteView, and this worked for single-object deletions. But as @Craig Blaszczyk points out, the DeleteView is for just that: deleting a single object. So I need to write a new view to delete multiple objects with an accompanying form and AJAX call that sends the ids array.

I have this working but it feels clunky and doesn't work very well. My AJAX script is here:

$.ajax({
    type: 'POST',
    url: '/dashboard/images/delete/',
    data: {'ids': ids},
    success: function() {
        console.log(date_time + ": AJAX call succeeded.");
    },
    error: function() {
        console.log(date_time + ": AJAX call failed!");
        console.log(date_time + ": Image ID: " + ids + ".");
    }
});

In this script (above the section shown here) I build an array of ids and send as data.

So in my CBV, I'm collecting the selected ids and deleting them:

def post(self, request, *args, **kwargs):    
    form = self.form_class(request.POST)
    GalleryImage.objects.filter(pk__in=request.POST.getlist('ids[]')).delete()
    return render(request, self.template_name, {'form': form})

Here is the form I'm using:

class DeleteImagesForm(forms.Form):
    ids = forms.ModelMultipleChoiceField(
        queryset=GalleryImage.objects.all(),
        widget=forms.CheckboxSelectMultiple(),
    )

What is a better way to be doing this? I feel like I hacked my way to this solution without very good practices in place.

Also, even thugh it seems to be working, I feel like I should be deleting these images after calling if form.is_valid().

Any final words before the bounty ends?

Upvotes: 4

Views: 1926

Answers (2)

Wagh
Wagh

Reputation: 4306

You can select checkbox and store the values of id's in one array and set that array to value of input tag.

Ex.

function updateTextAreanew() {
  var allVals = [];
    $('.questions_checkbox :checked').each(function() {
          allVals.push($(this).next().val());
    });
  $('.ups1').val(allVals);

}

$(function() {
  $('.questions_checkbox input').click(updateTextAreanew);

    updateTextAreanew();
});

Here we are detecting the checkbox click and stoaring the values in allVals array.

Now send this array which has all the id's to view using ajax and run for loop in view and delete the object.

in views

@csrf_exempt
def deleteitems(request):
    newdata = request.user
    profiledata = UserProfile.objects.get(user=newdata)
    swid = request.POST.getlist('newval[]') # ajax post data (which have all id's of GalleryImage objects)
    for one in swid:
        obj = GalleryImage.objects.get(id=one).delete()
    response = json.dumps({'data':'deleted'})
    return HttpResponse(response, mimetype="application/json")

Upvotes: 1

Craig Blaszczyk
Craig Blaszczyk

Reputation: 972

Your view is a DeleteView, which by definition only works with one item. To be able to delete multiple items I'd suggest that you make a new View, which has a form which expects the ids to which you want to delete. You'll then be able to write a ProcessFormView which iterates over the ids in the form and deletes each one.

Here's a sample view:

class MyView(FormView):
    form_class = MyForm
    template_name = 'mytemplate.html'

    def form_valid(self, form):
        # Process your ids here
        print form.cleaned_data['ids']
        # Prints [u'1', u'2']
        return super(MyView, self).form_valid(form)

    def get_form_kwargs(self):
        form_kwargs = super(MyView, self).get_form_kwargs()
        query =  Image.objects.all().values_list('id', flat=True)
        form_kwargs['image_ids'] = [(image_id, image_id) for image_id in query]
        return form_kwargs

And a sample form:

class MyForm(forms.Form):
    # This might be better as a ModelChoiecField
    ids = forms.MultipleChoiceField()#

    def __init__(self, image_ids, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['ids'].choices = image_ids

Upvotes: 3

Related Questions