﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
22689	inlines with sliced and ordered querysets save incorrectly when underlying data has changed since page load	Justin Hill	nobody	"Our Client model's Change page has an tabular inline for the client's Financial Transactions.  We use a custom formset to limit the transactions to the most recent 5 and to order them from newest to oldest.


{{{
class FinancialTransactionInlineFormset(BaseInlineFormSet):
	def get_queryset(self):
		qs = super(FinancialTransactionInlineFormset, self).get_queryset()
		return qs.order_by('-id')[:5]
}}}

If while you have the Change Client page open, someone else adds a new transaction, when you do the same, you'll find that while yours was added, some of the other transactions have changed.  The history page reports that you were the one that changed them.  In actuality, all you did was use the blank row at the bottom to add a new one.

{{{
Changed transaction_type for financial transaction ""client@company.net | 123
Changed transaction_type for financial transaction ""client@company.net | 456
Changed transaction_type for financial transaction ""client@company.net | 789
}}}

This is what I experienced in django 1.7b4.

It seems like django is having trouble deciding which inline forms have changed and which ones are new

In django 1.4.5 it throws an error because

{{{
obj = self._existing_object(pk_value)
}}}

in BaseModelFormset is setting obj to None

{{{
    def save_existing_objects(self, commit=True):
        self.changed_objects = []
        self.deleted_objects = []
        if not self.initial_forms:
            return []

        saved_instances = []
        for form in self.initial_forms:
            pk_name = self._pk_field.name
            raw_pk_value = form._raw_value(pk_name)

            # clean() for different types of PK fields can sometimes return
            # the model instance, and sometimes the PK. Handle either.
            pk_value = form.fields[pk_name].clean(raw_pk_value)
            pk_value = getattr(pk_value, 'pk', pk_value)

            obj = self._existing_object(pk_value)
            if self.can_delete and self._should_delete_form(form):
                self.deleted_objects.append(obj)
                obj.delete()
                continue
            if form.has_changed():
                self.changed_objects.append((obj, form.changed_data))
                saved_instances.append(self.save_existing(form, obj, commit=commit))
                if not commit:
                    self.saved_forms.append(form)
        return saved_instances
}}}


{{{
Traceback (most recent call last):

  File ""/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py"", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py"", line 366, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py"", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py"", line 89, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py"", line 196, in inner
    return view(request, *args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py"", line 25, in _wrapper
    return bound_func(*args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py"", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py"", line 21, in bound_func
    return func(self, *args2, **kwargs2)

  File ""/usr/local/lib/python2.7/dist-packages/django/db/transaction.py"", line 224, in inner
    return func(*args, **kwargs)

  File ""/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py"", line 1056, in change_view
    change_message = self.construct_change_message(request, form, formsets)

  File ""/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py"", line 682, in construct_change_message
    'name': force_unicode(changed_object._meta.verbose_name),

AttributeError: 'NoneType' object has no attribute '_meta'
}}}"	Bug	new	contrib.admin	1.7	Normal		admin inline		Accepted	0	0	0	0	0	0
