4

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?

nicorellius
  • 3,715
  • 4
  • 48
  • 79

2 Answers2

3

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
Craig Blaszczyk
  • 973
  • 1
  • 7
  • 20
  • Cool, this is good... Good point that `DeleteView` only works with one; I was just adding the code I have now to show what I'm working with. Thanks for your suggestions. I will try this out. Quick question, provided I build this view, will the AJAX I've provide still work? – nicorellius Dec 23 '14 at 18:59
  • Your ajax is only sending one id - see the `data: id` bit - so you'll need to change it to send an array of ids instead. – Craig Blaszczyk Dec 23 '14 at 19:14
  • I've been struggling with this for a while and can't figure out exactly how to put the pieces together. I've updated me OP. Can you suggest a preferred method and maybe offer some code starting points? In principle, what you state in your answer makes sense; I just can't get the pieces together. – nicorellius Dec 24 '14 at 07:12
  • Thanks for your suggestions. I have implemented what I could but am stuck. I updated my question if you care to take a look... Much appreciated. – nicorellius Dec 29 '14 at 11:42
  • Craig Blaszczyk - any final comments? I haven't awarded this bounty yet. Your answer helped but really didn't get me all the way... I just couldn't get your pieces to work together, probably because I'm missing something. – nicorellius Jan 05 '15 at 18:06
  • You should be deleting the models in the form_valid function, where I put "process the ids" as a comment. – Craig Blaszczyk Jan 05 '15 at 21:13
1

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")
Wagh
  • 4,202
  • 5
  • 39
  • 62