Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Model Formset: only track changes to those items that have been updated/saved in the set?

So, I'm using Django's Model Formset to produce sets of forms for different data. It is working great, but I want to add a feature where when a user displays the formset and, say, updates 2 out of the 10 items, I can track just the 2 updated, and output a message like "You have updated 2 items" kind-of-thing.

Do Django Model Formsets have a built in API for this? I can't seem to find it on the Django Docs.

I've tried various approaches but keep getting this when using the code offered by Peter below:

'Attendance' object has no attribute 'has_changed.' 

If I switch form.has_changed to formset.has_changed(), I get

'list' object has no attribute 'has_changed'

My View and Post method

class AttendanceView(TemplateView):

    template_name = 'example.html'

    def changed_forms(self, formset):
        return sum(1 for form in formset if form.has_changed())

def post(self, request, *args, **kwargs):
    formset = AttendanceFormSet(request.POST)
    if formset.is_valid():
        formset = formset.save()
        forms_changed = self.changed_forms(formset)
        context = self.get_context_data(**kwargs)
        context['total_changed_forms'] = forms_changed
        return self.render_to_response(context)
    else:
        return HttpResponse("POST failed")

So I figured it out, just change:

formset = formset.save() 

to

formset.save()
like image 432
Michael Sebastian Avatar asked Jun 13 '16 18:06

Michael Sebastian


People also ask

When saving How can you check if a field has changed?

Then in save method you can compare old and new value of field to check if the value has changed. @classmethod def from_db(cls, db, field_names, values): new = super(Alias, cls). from_db(db, field_names, values) # cache value went from the base new. _loaded_remote_image = values[field_names.

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.

What is a formset in Django?

A formset is a layer of abstraction to work with multiple forms on the same page. It can be best compared to a data grid. Let's say you have the following form: >>> from django import forms >>> class ArticleForm(forms.

What method can you use to check if from data has been changed when using a form instance?

Use the has_changed() method on your Form when you need to check if the form data has been changed from the initial data.


1 Answers

Formsets have a has_changed method which will report whether or not any of its forms have been changed. That's not exactly what you're looking for, but if you look at its implementation it should show you how to do it. That method is:

def has_changed(self):
    """
    Returns true if data in any form differs from initial.
    """
    return any(form.has_changed() for form in self)

So you can count changed forms with:

def changed_forms(formset):
    return sum(1 for form in formset if form.has_changed())

Or if you're comfortable using the integer meanings of boolean values:

    return sum(form.has_changed() for form in formset)

I personally find that unappealing compared to the more explicit mapping from true to 1, but opinions differ there.

like image 54
Peter DeGlopper Avatar answered Oct 19 '22 13:10

Peter DeGlopper